OSDN Git Service

32323e5d7b25683bd8b0ac0ca594437f42f069bf
[uclinux-h8/linux.git] / tools / perf / util / event.c
1 #include <linux/types.h>
2 #include <sys/mman.h>
3 #include "event.h"
4 #include "debug.h"
5 #include "hist.h"
6 #include "machine.h"
7 #include "sort.h"
8 #include "string.h"
9 #include "strlist.h"
10 #include "thread.h"
11 #include "thread_map.h"
12 #include "symbol/kallsyms.h"
13
14 static const char *perf_event__names[] = {
15         [0]                                     = "TOTAL",
16         [PERF_RECORD_MMAP]                      = "MMAP",
17         [PERF_RECORD_MMAP2]                     = "MMAP2",
18         [PERF_RECORD_LOST]                      = "LOST",
19         [PERF_RECORD_COMM]                      = "COMM",
20         [PERF_RECORD_EXIT]                      = "EXIT",
21         [PERF_RECORD_THROTTLE]                  = "THROTTLE",
22         [PERF_RECORD_UNTHROTTLE]                = "UNTHROTTLE",
23         [PERF_RECORD_FORK]                      = "FORK",
24         [PERF_RECORD_READ]                      = "READ",
25         [PERF_RECORD_SAMPLE]                    = "SAMPLE",
26         [PERF_RECORD_HEADER_ATTR]               = "ATTR",
27         [PERF_RECORD_HEADER_EVENT_TYPE]         = "EVENT_TYPE",
28         [PERF_RECORD_HEADER_TRACING_DATA]       = "TRACING_DATA",
29         [PERF_RECORD_HEADER_BUILD_ID]           = "BUILD_ID",
30         [PERF_RECORD_FINISHED_ROUND]            = "FINISHED_ROUND",
31         [PERF_RECORD_ID_INDEX]                  = "ID_INDEX",
32         [PERF_RECORD_AUXTRACE_INFO]             = "AUXTRACE_INFO",
33         [PERF_RECORD_AUXTRACE]                  = "AUXTRACE",
34         [PERF_RECORD_AUXTRACE_ERROR]            = "AUXTRACE_ERROR",
35 };
36
37 const char *perf_event__name(unsigned int id)
38 {
39         if (id >= ARRAY_SIZE(perf_event__names))
40                 return "INVALID";
41         if (!perf_event__names[id])
42                 return "UNKNOWN";
43         return perf_event__names[id];
44 }
45
46 static struct perf_sample synth_sample = {
47         .pid       = -1,
48         .tid       = -1,
49         .time      = -1,
50         .stream_id = -1,
51         .cpu       = -1,
52         .period    = 1,
53 };
54
55 /*
56  * Assumes that the first 4095 bytes of /proc/pid/stat contains
57  * the comm, tgid and ppid.
58  */
59 static int perf_event__get_comm_ids(pid_t pid, char *comm, size_t len,
60                                     pid_t *tgid, pid_t *ppid)
61 {
62         char filename[PATH_MAX];
63         char bf[4096];
64         int fd;
65         size_t size = 0, n;
66         char *nl, *name, *tgids, *ppids;
67
68         *tgid = -1;
69         *ppid = -1;
70
71         snprintf(filename, sizeof(filename), "/proc/%d/status", pid);
72
73         fd = open(filename, O_RDONLY);
74         if (fd < 0) {
75                 pr_debug("couldn't open %s\n", filename);
76                 return -1;
77         }
78
79         n = read(fd, bf, sizeof(bf) - 1);
80         close(fd);
81         if (n <= 0) {
82                 pr_warning("Couldn't get COMM, tigd and ppid for pid %d\n",
83                            pid);
84                 return -1;
85         }
86         bf[n] = '\0';
87
88         name = strstr(bf, "Name:");
89         tgids = strstr(bf, "Tgid:");
90         ppids = strstr(bf, "PPid:");
91
92         if (name) {
93                 name += 5;  /* strlen("Name:") */
94
95                 while (*name && isspace(*name))
96                         ++name;
97
98                 nl = strchr(name, '\n');
99                 if (nl)
100                         *nl = '\0';
101
102                 size = strlen(name);
103                 if (size >= len)
104                         size = len - 1;
105                 memcpy(comm, name, size);
106                 comm[size] = '\0';
107         } else {
108                 pr_debug("Name: string not found for pid %d\n", pid);
109         }
110
111         if (tgids) {
112                 tgids += 5;  /* strlen("Tgid:") */
113                 *tgid = atoi(tgids);
114         } else {
115                 pr_debug("Tgid: string not found for pid %d\n", pid);
116         }
117
118         if (ppids) {
119                 ppids += 5;  /* strlen("PPid:") */
120                 *ppid = atoi(ppids);
121         } else {
122                 pr_debug("PPid: string not found for pid %d\n", pid);
123         }
124
125         return 0;
126 }
127
128 static int perf_event__prepare_comm(union perf_event *event, pid_t pid,
129                                     struct machine *machine,
130                                     pid_t *tgid, pid_t *ppid)
131 {
132         size_t size;
133
134         *ppid = -1;
135
136         memset(&event->comm, 0, sizeof(event->comm));
137
138         if (machine__is_host(machine)) {
139                 if (perf_event__get_comm_ids(pid, event->comm.comm,
140                                              sizeof(event->comm.comm),
141                                              tgid, ppid) != 0) {
142                         return -1;
143                 }
144         } else {
145                 *tgid = machine->pid;
146         }
147
148         if (*tgid < 0)
149                 return -1;
150
151         event->comm.pid = *tgid;
152         event->comm.header.type = PERF_RECORD_COMM;
153
154         size = strlen(event->comm.comm) + 1;
155         size = PERF_ALIGN(size, sizeof(u64));
156         memset(event->comm.comm + size, 0, machine->id_hdr_size);
157         event->comm.header.size = (sizeof(event->comm) -
158                                 (sizeof(event->comm.comm) - size) +
159                                 machine->id_hdr_size);
160         event->comm.tid = pid;
161
162         return 0;
163 }
164
165 static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
166                                          union perf_event *event, pid_t pid,
167                                          perf_event__handler_t process,
168                                          struct machine *machine)
169 {
170         pid_t tgid, ppid;
171
172         if (perf_event__prepare_comm(event, pid, machine, &tgid, &ppid) != 0)
173                 return -1;
174
175         if (process(tool, event, &synth_sample, machine) != 0)
176                 return -1;
177
178         return tgid;
179 }
180
181 static int perf_event__synthesize_fork(struct perf_tool *tool,
182                                        union perf_event *event,
183                                        pid_t pid, pid_t tgid, pid_t ppid,
184                                        perf_event__handler_t process,
185                                        struct machine *machine)
186 {
187         memset(&event->fork, 0, sizeof(event->fork) + machine->id_hdr_size);
188
189         /*
190          * for main thread set parent to ppid from status file. For other
191          * threads set parent pid to main thread. ie., assume main thread
192          * spawns all threads in a process
193         */
194         if (tgid == pid) {
195                 event->fork.ppid = ppid;
196                 event->fork.ptid = ppid;
197         } else {
198                 event->fork.ppid = tgid;
199                 event->fork.ptid = tgid;
200         }
201         event->fork.pid  = tgid;
202         event->fork.tid  = pid;
203         event->fork.header.type = PERF_RECORD_FORK;
204
205         event->fork.header.size = (sizeof(event->fork) + machine->id_hdr_size);
206
207         if (process(tool, event, &synth_sample, machine) != 0)
208                 return -1;
209
210         return 0;
211 }
212
213 int perf_event__synthesize_mmap_events(struct perf_tool *tool,
214                                        union perf_event *event,
215                                        pid_t pid, pid_t tgid,
216                                        perf_event__handler_t process,
217                                        struct machine *machine,
218                                        bool mmap_data)
219 {
220         char filename[PATH_MAX];
221         FILE *fp;
222         int rc = 0;
223
224         if (machine__is_default_guest(machine))
225                 return 0;
226
227         snprintf(filename, sizeof(filename), "%s/proc/%d/maps",
228                  machine->root_dir, pid);
229
230         fp = fopen(filename, "r");
231         if (fp == NULL) {
232                 /*
233                  * We raced with a task exiting - just return:
234                  */
235                 pr_debug("couldn't open %s\n", filename);
236                 return -1;
237         }
238
239         event->header.type = PERF_RECORD_MMAP2;
240
241         while (1) {
242                 char bf[BUFSIZ];
243                 char prot[5];
244                 char execname[PATH_MAX];
245                 char anonstr[] = "//anon";
246                 unsigned int ino;
247                 size_t size;
248                 ssize_t n;
249
250                 if (fgets(bf, sizeof(bf), fp) == NULL)
251                         break;
252
253                 /* ensure null termination since stack will be reused. */
254                 strcpy(execname, "");
255
256                 /* 00400000-0040c000 r-xp 00000000 fd:01 41038  /bin/cat */
257                 n = sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %x:%x %u %s\n",
258                        &event->mmap2.start, &event->mmap2.len, prot,
259                        &event->mmap2.pgoff, &event->mmap2.maj,
260                        &event->mmap2.min,
261                        &ino, execname);
262
263                 /*
264                  * Anon maps don't have the execname.
265                  */
266                 if (n < 7)
267                         continue;
268
269                 event->mmap2.ino = (u64)ino;
270
271                 /*
272                  * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c
273                  */
274                 if (machine__is_host(machine))
275                         event->header.misc = PERF_RECORD_MISC_USER;
276                 else
277                         event->header.misc = PERF_RECORD_MISC_GUEST_USER;
278
279                 /* map protection and flags bits */
280                 event->mmap2.prot = 0;
281                 event->mmap2.flags = 0;
282                 if (prot[0] == 'r')
283                         event->mmap2.prot |= PROT_READ;
284                 if (prot[1] == 'w')
285                         event->mmap2.prot |= PROT_WRITE;
286                 if (prot[2] == 'x')
287                         event->mmap2.prot |= PROT_EXEC;
288
289                 if (prot[3] == 's')
290                         event->mmap2.flags |= MAP_SHARED;
291                 else
292                         event->mmap2.flags |= MAP_PRIVATE;
293
294                 if (prot[2] != 'x') {
295                         if (!mmap_data || prot[0] != 'r')
296                                 continue;
297
298                         event->header.misc |= PERF_RECORD_MISC_MMAP_DATA;
299                 }
300
301                 if (!strcmp(execname, ""))
302                         strcpy(execname, anonstr);
303
304                 size = strlen(execname) + 1;
305                 memcpy(event->mmap2.filename, execname, size);
306                 size = PERF_ALIGN(size, sizeof(u64));
307                 event->mmap2.len -= event->mmap.start;
308                 event->mmap2.header.size = (sizeof(event->mmap2) -
309                                         (sizeof(event->mmap2.filename) - size));
310                 memset(event->mmap2.filename + size, 0, machine->id_hdr_size);
311                 event->mmap2.header.size += machine->id_hdr_size;
312                 event->mmap2.pid = tgid;
313                 event->mmap2.tid = pid;
314
315                 if (process(tool, event, &synth_sample, machine) != 0) {
316                         rc = -1;
317                         break;
318                 }
319         }
320
321         fclose(fp);
322         return rc;
323 }
324
325 int perf_event__synthesize_modules(struct perf_tool *tool,
326                                    perf_event__handler_t process,
327                                    struct machine *machine)
328 {
329         int rc = 0;
330         struct rb_node *nd;
331         struct map_groups *kmaps = &machine->kmaps;
332         union perf_event *event = zalloc((sizeof(event->mmap) +
333                                           machine->id_hdr_size));
334         if (event == NULL) {
335                 pr_debug("Not enough memory synthesizing mmap event "
336                          "for kernel modules\n");
337                 return -1;
338         }
339
340         event->header.type = PERF_RECORD_MMAP;
341
342         /*
343          * kernel uses 0 for user space maps, see kernel/perf_event.c
344          * __perf_event_mmap
345          */
346         if (machine__is_host(machine))
347                 event->header.misc = PERF_RECORD_MISC_KERNEL;
348         else
349                 event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
350
351         for (nd = rb_first(&kmaps->maps[MAP__FUNCTION]);
352              nd; nd = rb_next(nd)) {
353                 size_t size;
354                 struct map *pos = rb_entry(nd, struct map, rb_node);
355
356                 if (pos->dso->kernel)
357                         continue;
358
359                 size = PERF_ALIGN(pos->dso->long_name_len + 1, sizeof(u64));
360                 event->mmap.header.type = PERF_RECORD_MMAP;
361                 event->mmap.header.size = (sizeof(event->mmap) -
362                                         (sizeof(event->mmap.filename) - size));
363                 memset(event->mmap.filename + size, 0, machine->id_hdr_size);
364                 event->mmap.header.size += machine->id_hdr_size;
365                 event->mmap.start = pos->start;
366                 event->mmap.len   = pos->end - pos->start;
367                 event->mmap.pid   = machine->pid;
368
369                 memcpy(event->mmap.filename, pos->dso->long_name,
370                        pos->dso->long_name_len + 1);
371                 if (process(tool, event, &synth_sample, machine) != 0) {
372                         rc = -1;
373                         break;
374                 }
375         }
376
377         free(event);
378         return rc;
379 }
380
381 static int __event__synthesize_thread(union perf_event *comm_event,
382                                       union perf_event *mmap_event,
383                                       union perf_event *fork_event,
384                                       pid_t pid, int full,
385                                           perf_event__handler_t process,
386                                       struct perf_tool *tool,
387                                       struct machine *machine, bool mmap_data)
388 {
389         char filename[PATH_MAX];
390         DIR *tasks;
391         struct dirent dirent, *next;
392         pid_t tgid, ppid;
393         int rc = 0;
394
395         /* special case: only send one comm event using passed in pid */
396         if (!full) {
397                 tgid = perf_event__synthesize_comm(tool, comm_event, pid,
398                                                    process, machine);
399
400                 if (tgid == -1)
401                         return -1;
402
403                 return perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
404                                                           process, machine, mmap_data);
405         }
406
407         if (machine__is_default_guest(machine))
408                 return 0;
409
410         snprintf(filename, sizeof(filename), "%s/proc/%d/task",
411                  machine->root_dir, pid);
412
413         tasks = opendir(filename);
414         if (tasks == NULL) {
415                 pr_debug("couldn't open %s\n", filename);
416                 return 0;
417         }
418
419         while (!readdir_r(tasks, &dirent, &next) && next) {
420                 char *end;
421                 pid_t _pid;
422
423                 _pid = strtol(dirent.d_name, &end, 10);
424                 if (*end)
425                         continue;
426
427                 rc = -1;
428                 if (perf_event__prepare_comm(comm_event, _pid, machine,
429                                              &tgid, &ppid) != 0)
430                         break;
431
432                 if (perf_event__synthesize_fork(tool, fork_event, _pid, tgid,
433                                                 ppid, process, machine) < 0)
434                         break;
435                 /*
436                  * Send the prepared comm event
437                  */
438                 if (process(tool, comm_event, &synth_sample, machine) != 0)
439                         break;
440
441                 rc = 0;
442                 if (_pid == pid) {
443                         /* process the parent's maps too */
444                         rc = perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
445                                                 process, machine, mmap_data);
446                         if (rc)
447                                 break;
448                 }
449         }
450
451         closedir(tasks);
452         return rc;
453 }
454
455 int perf_event__synthesize_thread_map(struct perf_tool *tool,
456                                       struct thread_map *threads,
457                                       perf_event__handler_t process,
458                                       struct machine *machine,
459                                       bool mmap_data)
460 {
461         union perf_event *comm_event, *mmap_event, *fork_event;
462         int err = -1, thread, j;
463
464         comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size);
465         if (comm_event == NULL)
466                 goto out;
467
468         mmap_event = malloc(sizeof(mmap_event->mmap) + machine->id_hdr_size);
469         if (mmap_event == NULL)
470                 goto out_free_comm;
471
472         fork_event = malloc(sizeof(fork_event->fork) + machine->id_hdr_size);
473         if (fork_event == NULL)
474                 goto out_free_mmap;
475
476         err = 0;
477         for (thread = 0; thread < threads->nr; ++thread) {
478                 if (__event__synthesize_thread(comm_event, mmap_event,
479                                                fork_event,
480                                                threads->map[thread], 0,
481                                                process, tool, machine,
482                                                mmap_data)) {
483                         err = -1;
484                         break;
485                 }
486
487                 /*
488                  * comm.pid is set to thread group id by
489                  * perf_event__synthesize_comm
490                  */
491                 if ((int) comm_event->comm.pid != threads->map[thread]) {
492                         bool need_leader = true;
493
494                         /* is thread group leader in thread_map? */
495                         for (j = 0; j < threads->nr; ++j) {
496                                 if ((int) comm_event->comm.pid == threads->map[j]) {
497                                         need_leader = false;
498                                         break;
499                                 }
500                         }
501
502                         /* if not, generate events for it */
503                         if (need_leader &&
504                             __event__synthesize_thread(comm_event, mmap_event,
505                                                        fork_event,
506                                                        comm_event->comm.pid, 0,
507                                                        process, tool, machine,
508                                                        mmap_data)) {
509                                 err = -1;
510                                 break;
511                         }
512                 }
513         }
514         free(fork_event);
515 out_free_mmap:
516         free(mmap_event);
517 out_free_comm:
518         free(comm_event);
519 out:
520         return err;
521 }
522
523 int perf_event__synthesize_threads(struct perf_tool *tool,
524                                    perf_event__handler_t process,
525                                    struct machine *machine, bool mmap_data)
526 {
527         DIR *proc;
528         char proc_path[PATH_MAX];
529         struct dirent dirent, *next;
530         union perf_event *comm_event, *mmap_event, *fork_event;
531         int err = -1;
532
533         if (machine__is_default_guest(machine))
534                 return 0;
535
536         comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size);
537         if (comm_event == NULL)
538                 goto out;
539
540         mmap_event = malloc(sizeof(mmap_event->mmap) + machine->id_hdr_size);
541         if (mmap_event == NULL)
542                 goto out_free_comm;
543
544         fork_event = malloc(sizeof(fork_event->fork) + machine->id_hdr_size);
545         if (fork_event == NULL)
546                 goto out_free_mmap;
547
548         snprintf(proc_path, sizeof(proc_path), "%s/proc", machine->root_dir);
549         proc = opendir(proc_path);
550
551         if (proc == NULL)
552                 goto out_free_fork;
553
554         while (!readdir_r(proc, &dirent, &next) && next) {
555                 char *end;
556                 pid_t pid = strtol(dirent.d_name, &end, 10);
557
558                 if (*end) /* only interested in proper numerical dirents */
559                         continue;
560                 /*
561                  * We may race with exiting thread, so don't stop just because
562                  * one thread couldn't be synthesized.
563                  */
564                 __event__synthesize_thread(comm_event, mmap_event, fork_event, pid,
565                                            1, process, tool, machine, mmap_data);
566         }
567
568         err = 0;
569         closedir(proc);
570 out_free_fork:
571         free(fork_event);
572 out_free_mmap:
573         free(mmap_event);
574 out_free_comm:
575         free(comm_event);
576 out:
577         return err;
578 }
579
580 struct process_symbol_args {
581         const char *name;
582         u64        start;
583 };
584
585 static int find_symbol_cb(void *arg, const char *name, char type,
586                           u64 start)
587 {
588         struct process_symbol_args *args = arg;
589
590         /*
591          * Must be a function or at least an alias, as in PARISC64, where "_text" is
592          * an 'A' to the same address as "_stext".
593          */
594         if (!(symbol_type__is_a(type, MAP__FUNCTION) ||
595               type == 'A') || strcmp(name, args->name))
596                 return 0;
597
598         args->start = start;
599         return 1;
600 }
601
602 u64 kallsyms__get_function_start(const char *kallsyms_filename,
603                                  const char *symbol_name)
604 {
605         struct process_symbol_args args = { .name = symbol_name, };
606
607         if (kallsyms__parse(kallsyms_filename, &args, find_symbol_cb) <= 0)
608                 return 0;
609
610         return args.start;
611 }
612
613 int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
614                                        perf_event__handler_t process,
615                                        struct machine *machine)
616 {
617         size_t size;
618         const char *mmap_name;
619         char name_buff[PATH_MAX];
620         struct map *map;
621         struct kmap *kmap;
622         int err;
623         union perf_event *event;
624
625         if (machine->vmlinux_maps[0] == NULL)
626                 return -1;
627
628         /*
629          * We should get this from /sys/kernel/sections/.text, but till that is
630          * available use this, and after it is use this as a fallback for older
631          * kernels.
632          */
633         event = zalloc((sizeof(event->mmap) + machine->id_hdr_size));
634         if (event == NULL) {
635                 pr_debug("Not enough memory synthesizing mmap event "
636                          "for kernel modules\n");
637                 return -1;
638         }
639
640         mmap_name = machine__mmap_name(machine, name_buff, sizeof(name_buff));
641         if (machine__is_host(machine)) {
642                 /*
643                  * kernel uses PERF_RECORD_MISC_USER for user space maps,
644                  * see kernel/perf_event.c __perf_event_mmap
645                  */
646                 event->header.misc = PERF_RECORD_MISC_KERNEL;
647         } else {
648                 event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
649         }
650
651         map = machine->vmlinux_maps[MAP__FUNCTION];
652         kmap = map__kmap(map);
653         size = snprintf(event->mmap.filename, sizeof(event->mmap.filename),
654                         "%s%s", mmap_name, kmap->ref_reloc_sym->name) + 1;
655         size = PERF_ALIGN(size, sizeof(u64));
656         event->mmap.header.type = PERF_RECORD_MMAP;
657         event->mmap.header.size = (sizeof(event->mmap) -
658                         (sizeof(event->mmap.filename) - size) + machine->id_hdr_size);
659         event->mmap.pgoff = kmap->ref_reloc_sym->addr;
660         event->mmap.start = map->start;
661         event->mmap.len   = map->end - event->mmap.start;
662         event->mmap.pid   = machine->pid;
663
664         err = process(tool, event, &synth_sample, machine);
665         free(event);
666
667         return err;
668 }
669
670 size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp)
671 {
672         const char *s;
673
674         if (event->header.misc & PERF_RECORD_MISC_COMM_EXEC)
675                 s = " exec";
676         else
677                 s = "";
678
679         return fprintf(fp, "%s: %s:%d/%d\n", s, event->comm.comm, event->comm.pid, event->comm.tid);
680 }
681
682 int perf_event__process_comm(struct perf_tool *tool __maybe_unused,
683                              union perf_event *event,
684                              struct perf_sample *sample,
685                              struct machine *machine)
686 {
687         return machine__process_comm_event(machine, event, sample);
688 }
689
690 int perf_event__process_lost(struct perf_tool *tool __maybe_unused,
691                              union perf_event *event,
692                              struct perf_sample *sample,
693                              struct machine *machine)
694 {
695         return machine__process_lost_event(machine, event, sample);
696 }
697
698 size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)
699 {
700         return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %c %s\n",
701                        event->mmap.pid, event->mmap.tid, event->mmap.start,
702                        event->mmap.len, event->mmap.pgoff,
703                        (event->header.misc & PERF_RECORD_MISC_MMAP_DATA) ? 'r' : 'x',
704                        event->mmap.filename);
705 }
706
707 size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp)
708 {
709         return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64
710                            " %02x:%02x %"PRIu64" %"PRIu64"]: %c%c%c%c %s\n",
711                        event->mmap2.pid, event->mmap2.tid, event->mmap2.start,
712                        event->mmap2.len, event->mmap2.pgoff, event->mmap2.maj,
713                        event->mmap2.min, event->mmap2.ino,
714                        event->mmap2.ino_generation,
715                        (event->mmap2.prot & PROT_READ) ? 'r' : '-',
716                        (event->mmap2.prot & PROT_WRITE) ? 'w' : '-',
717                        (event->mmap2.prot & PROT_EXEC) ? 'x' : '-',
718                        (event->mmap2.flags & MAP_SHARED) ? 's' : 'p',
719                        event->mmap2.filename);
720 }
721
722 int perf_event__process_mmap(struct perf_tool *tool __maybe_unused,
723                              union perf_event *event,
724                              struct perf_sample *sample,
725                              struct machine *machine)
726 {
727         return machine__process_mmap_event(machine, event, sample);
728 }
729
730 int perf_event__process_mmap2(struct perf_tool *tool __maybe_unused,
731                              union perf_event *event,
732                              struct perf_sample *sample,
733                              struct machine *machine)
734 {
735         return machine__process_mmap2_event(machine, event, sample);
736 }
737
738 size_t perf_event__fprintf_task(union perf_event *event, FILE *fp)
739 {
740         return fprintf(fp, "(%d:%d):(%d:%d)\n",
741                        event->fork.pid, event->fork.tid,
742                        event->fork.ppid, event->fork.ptid);
743 }
744
745 int perf_event__process_fork(struct perf_tool *tool __maybe_unused,
746                              union perf_event *event,
747                              struct perf_sample *sample,
748                              struct machine *machine)
749 {
750         return machine__process_fork_event(machine, event, sample);
751 }
752
753 int perf_event__process_exit(struct perf_tool *tool __maybe_unused,
754                              union perf_event *event,
755                              struct perf_sample *sample,
756                              struct machine *machine)
757 {
758         return machine__process_exit_event(machine, event, sample);
759 }
760
761 size_t perf_event__fprintf(union perf_event *event, FILE *fp)
762 {
763         size_t ret = fprintf(fp, "PERF_RECORD_%s",
764                              perf_event__name(event->header.type));
765
766         switch (event->header.type) {
767         case PERF_RECORD_COMM:
768                 ret += perf_event__fprintf_comm(event, fp);
769                 break;
770         case PERF_RECORD_FORK:
771         case PERF_RECORD_EXIT:
772                 ret += perf_event__fprintf_task(event, fp);
773                 break;
774         case PERF_RECORD_MMAP:
775                 ret += perf_event__fprintf_mmap(event, fp);
776                 break;
777         case PERF_RECORD_MMAP2:
778                 ret += perf_event__fprintf_mmap2(event, fp);
779                 break;
780         default:
781                 ret += fprintf(fp, "\n");
782         }
783
784         return ret;
785 }
786
787 int perf_event__process(struct perf_tool *tool __maybe_unused,
788                         union perf_event *event,
789                         struct perf_sample *sample,
790                         struct machine *machine)
791 {
792         return machine__process_event(machine, event, sample);
793 }
794
795 void thread__find_addr_map(struct thread *thread, u8 cpumode,
796                            enum map_type type, u64 addr,
797                            struct addr_location *al)
798 {
799         struct map_groups *mg = thread->mg;
800         struct machine *machine = mg->machine;
801         bool load_map = false;
802
803         al->machine = machine;
804         al->thread = thread;
805         al->addr = addr;
806         al->cpumode = cpumode;
807         al->filtered = 0;
808
809         if (machine == NULL) {
810                 al->map = NULL;
811                 return;
812         }
813
814         if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) {
815                 al->level = 'k';
816                 mg = &machine->kmaps;
817                 load_map = true;
818         } else if (cpumode == PERF_RECORD_MISC_USER && perf_host) {
819                 al->level = '.';
820         } else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) {
821                 al->level = 'g';
822                 mg = &machine->kmaps;
823                 load_map = true;
824         } else if (cpumode == PERF_RECORD_MISC_GUEST_USER && perf_guest) {
825                 al->level = 'u';
826         } else {
827                 al->level = 'H';
828                 al->map = NULL;
829
830                 if ((cpumode == PERF_RECORD_MISC_GUEST_USER ||
831                         cpumode == PERF_RECORD_MISC_GUEST_KERNEL) &&
832                         !perf_guest)
833                         al->filtered |= (1 << HIST_FILTER__GUEST);
834                 if ((cpumode == PERF_RECORD_MISC_USER ||
835                         cpumode == PERF_RECORD_MISC_KERNEL) &&
836                         !perf_host)
837                         al->filtered |= (1 << HIST_FILTER__HOST);
838
839                 return;
840         }
841 try_again:
842         al->map = map_groups__find(mg, type, al->addr);
843         if (al->map == NULL) {
844                 /*
845                  * If this is outside of all known maps, and is a negative
846                  * address, try to look it up in the kernel dso, as it might be
847                  * a vsyscall or vdso (which executes in user-mode).
848                  *
849                  * XXX This is nasty, we should have a symbol list in the
850                  * "[vdso]" dso, but for now lets use the old trick of looking
851                  * in the whole kernel symbol list.
852                  */
853                 if (cpumode == PERF_RECORD_MISC_USER && machine &&
854                     mg != &machine->kmaps &&
855                     machine__kernel_ip(machine, al->addr)) {
856                         mg = &machine->kmaps;
857                         load_map = true;
858                         goto try_again;
859                 }
860         } else {
861                 /*
862                  * Kernel maps might be changed when loading symbols so loading
863                  * must be done prior to using kernel maps.
864                  */
865                 if (load_map)
866                         map__load(al->map, machine->symbol_filter);
867                 al->addr = al->map->map_ip(al->map, al->addr);
868         }
869 }
870
871 void thread__find_addr_location(struct thread *thread,
872                                 u8 cpumode, enum map_type type, u64 addr,
873                                 struct addr_location *al)
874 {
875         thread__find_addr_map(thread, cpumode, type, addr, al);
876         if (al->map != NULL)
877                 al->sym = map__find_symbol(al->map, al->addr,
878                                            thread->mg->machine->symbol_filter);
879         else
880                 al->sym = NULL;
881 }
882
883 int perf_event__preprocess_sample(const union perf_event *event,
884                                   struct machine *machine,
885                                   struct addr_location *al,
886                                   struct perf_sample *sample)
887 {
888         u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
889         struct thread *thread = machine__findnew_thread(machine, sample->pid,
890                                                         sample->tid);
891
892         if (thread == NULL)
893                 return -1;
894
895         dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid);
896         /*
897          * Have we already created the kernel maps for this machine?
898          *
899          * This should have happened earlier, when we processed the kernel MMAP
900          * events, but for older perf.data files there was no such thing, so do
901          * it now.
902          */
903         if (cpumode == PERF_RECORD_MISC_KERNEL &&
904             machine->vmlinux_maps[MAP__FUNCTION] == NULL)
905                 machine__create_kernel_maps(machine);
906
907         thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->ip, al);
908         dump_printf(" ...... dso: %s\n",
909                     al->map ? al->map->dso->long_name :
910                         al->level == 'H' ? "[hypervisor]" : "<not found>");
911
912         if (thread__is_filtered(thread))
913                 al->filtered |= (1 << HIST_FILTER__THREAD);
914
915         al->sym = NULL;
916         al->cpu = sample->cpu;
917
918         if (al->map) {
919                 struct dso *dso = al->map->dso;
920
921                 if (symbol_conf.dso_list &&
922                     (!dso || !(strlist__has_entry(symbol_conf.dso_list,
923                                                   dso->short_name) ||
924                                (dso->short_name != dso->long_name &&
925                                 strlist__has_entry(symbol_conf.dso_list,
926                                                    dso->long_name))))) {
927                         al->filtered |= (1 << HIST_FILTER__DSO);
928                 }
929
930                 al->sym = map__find_symbol(al->map, al->addr,
931                                            machine->symbol_filter);
932         }
933
934         if (symbol_conf.sym_list &&
935                 (!al->sym || !strlist__has_entry(symbol_conf.sym_list,
936                                                 al->sym->name))) {
937                 al->filtered |= (1 << HIST_FILTER__SYMBOL);
938         }
939
940         return 0;
941 }
942
943 bool is_bts_event(struct perf_event_attr *attr)
944 {
945         return attr->type == PERF_TYPE_HARDWARE &&
946                (attr->config & PERF_COUNT_HW_BRANCH_INSTRUCTIONS) &&
947                attr->sample_period == 1;
948 }
949
950 bool sample_addr_correlates_sym(struct perf_event_attr *attr)
951 {
952         if (attr->type == PERF_TYPE_SOFTWARE &&
953             (attr->config == PERF_COUNT_SW_PAGE_FAULTS ||
954              attr->config == PERF_COUNT_SW_PAGE_FAULTS_MIN ||
955              attr->config == PERF_COUNT_SW_PAGE_FAULTS_MAJ))
956                 return true;
957
958         if (is_bts_event(attr))
959                 return true;
960
961         return false;
962 }
963
964 void perf_event__preprocess_sample_addr(union perf_event *event,
965                                         struct perf_sample *sample,
966                                         struct thread *thread,
967                                         struct addr_location *al)
968 {
969         u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
970
971         thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->addr, al);
972         if (!al->map)
973                 thread__find_addr_map(thread, cpumode, MAP__VARIABLE,
974                                       sample->addr, al);
975
976         al->cpu = sample->cpu;
977         al->sym = NULL;
978
979         if (al->map)
980                 al->sym = map__find_symbol(al->map, al->addr, NULL);
981 }