]> Git Repo - linux.git/blob - tools/perf/util/event.c
driver core: Return proper error code when dev_set_name() fails
[linux.git] / tools / perf / util / event.c
1 #include <errno.h>
2 #include <fcntl.h>
3 #include <inttypes.h>
4 #include <linux/kernel.h>
5 #include <linux/types.h>
6 #include <perf/cpumap.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <unistd.h>
10 #include <uapi/linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */
11 #include <linux/perf_event.h>
12 #include <linux/zalloc.h>
13 #include "cpumap.h"
14 #include "dso.h"
15 #include "event.h"
16 #include "debug.h"
17 #include "hist.h"
18 #include "machine.h"
19 #include "sort.h"
20 #include "string2.h"
21 #include "strlist.h"
22 #include "thread.h"
23 #include "thread_map.h"
24 #include "time-utils.h"
25 #include <linux/ctype.h>
26 #include "map.h"
27 #include "util/namespaces.h"
28 #include "symbol.h"
29 #include "symbol/kallsyms.h"
30 #include "asm/bug.h"
31 #include "stat.h"
32 #include "session.h"
33 #include "bpf-event.h"
34 #include "print_binary.h"
35 #include "tool.h"
36 #include "util.h"
37
38 static const char *perf_event__names[] = {
39         [0]                                     = "TOTAL",
40         [PERF_RECORD_MMAP]                      = "MMAP",
41         [PERF_RECORD_MMAP2]                     = "MMAP2",
42         [PERF_RECORD_LOST]                      = "LOST",
43         [PERF_RECORD_COMM]                      = "COMM",
44         [PERF_RECORD_EXIT]                      = "EXIT",
45         [PERF_RECORD_THROTTLE]                  = "THROTTLE",
46         [PERF_RECORD_UNTHROTTLE]                = "UNTHROTTLE",
47         [PERF_RECORD_FORK]                      = "FORK",
48         [PERF_RECORD_READ]                      = "READ",
49         [PERF_RECORD_SAMPLE]                    = "SAMPLE",
50         [PERF_RECORD_AUX]                       = "AUX",
51         [PERF_RECORD_ITRACE_START]              = "ITRACE_START",
52         [PERF_RECORD_LOST_SAMPLES]              = "LOST_SAMPLES",
53         [PERF_RECORD_SWITCH]                    = "SWITCH",
54         [PERF_RECORD_SWITCH_CPU_WIDE]           = "SWITCH_CPU_WIDE",
55         [PERF_RECORD_NAMESPACES]                = "NAMESPACES",
56         [PERF_RECORD_KSYMBOL]                   = "KSYMBOL",
57         [PERF_RECORD_BPF_EVENT]                 = "BPF_EVENT",
58         [PERF_RECORD_CGROUP]                    = "CGROUP",
59         [PERF_RECORD_TEXT_POKE]                 = "TEXT_POKE",
60         [PERF_RECORD_AUX_OUTPUT_HW_ID]          = "AUX_OUTPUT_HW_ID",
61         [PERF_RECORD_HEADER_ATTR]               = "ATTR",
62         [PERF_RECORD_HEADER_EVENT_TYPE]         = "EVENT_TYPE",
63         [PERF_RECORD_HEADER_TRACING_DATA]       = "TRACING_DATA",
64         [PERF_RECORD_HEADER_BUILD_ID]           = "BUILD_ID",
65         [PERF_RECORD_FINISHED_ROUND]            = "FINISHED_ROUND",
66         [PERF_RECORD_ID_INDEX]                  = "ID_INDEX",
67         [PERF_RECORD_AUXTRACE_INFO]             = "AUXTRACE_INFO",
68         [PERF_RECORD_AUXTRACE]                  = "AUXTRACE",
69         [PERF_RECORD_AUXTRACE_ERROR]            = "AUXTRACE_ERROR",
70         [PERF_RECORD_THREAD_MAP]                = "THREAD_MAP",
71         [PERF_RECORD_CPU_MAP]                   = "CPU_MAP",
72         [PERF_RECORD_STAT_CONFIG]               = "STAT_CONFIG",
73         [PERF_RECORD_STAT]                      = "STAT",
74         [PERF_RECORD_STAT_ROUND]                = "STAT_ROUND",
75         [PERF_RECORD_EVENT_UPDATE]              = "EVENT_UPDATE",
76         [PERF_RECORD_TIME_CONV]                 = "TIME_CONV",
77         [PERF_RECORD_HEADER_FEATURE]            = "FEATURE",
78         [PERF_RECORD_COMPRESSED]                = "COMPRESSED",
79         [PERF_RECORD_FINISHED_INIT]             = "FINISHED_INIT",
80 };
81
82 const char *perf_event__name(unsigned int id)
83 {
84         if (id >= ARRAY_SIZE(perf_event__names))
85                 return "INVALID";
86         if (!perf_event__names[id])
87                 return "UNKNOWN";
88         return perf_event__names[id];
89 }
90
91 struct process_symbol_args {
92         const char *name;
93         u64        start;
94 };
95
96 static int find_symbol_cb(void *arg, const char *name, char type,
97                           u64 start)
98 {
99         struct process_symbol_args *args = arg;
100
101         /*
102          * Must be a function or at least an alias, as in PARISC64, where "_text" is
103          * an 'A' to the same address as "_stext".
104          */
105         if (!(kallsyms__is_function(type) ||
106               type == 'A') || strcmp(name, args->name))
107                 return 0;
108
109         args->start = start;
110         return 1;
111 }
112
113 int kallsyms__get_function_start(const char *kallsyms_filename,
114                                  const char *symbol_name, u64 *addr)
115 {
116         struct process_symbol_args args = { .name = symbol_name, };
117
118         if (kallsyms__parse(kallsyms_filename, &args, find_symbol_cb) <= 0)
119                 return -1;
120
121         *addr = args.start;
122         return 0;
123 }
124
125 void perf_event__read_stat_config(struct perf_stat_config *config,
126                                   struct perf_record_stat_config *event)
127 {
128         unsigned i;
129
130         for (i = 0; i < event->nr; i++) {
131
132                 switch (event->data[i].tag) {
133 #define CASE(__term, __val)                                     \
134                 case PERF_STAT_CONFIG_TERM__##__term:           \
135                         config->__val = event->data[i].val;     \
136                         break;
137
138                 CASE(AGGR_MODE,  aggr_mode)
139                 CASE(SCALE,      scale)
140                 CASE(INTERVAL,   interval)
141                 CASE(AGGR_LEVEL, aggr_level)
142 #undef CASE
143                 default:
144                         pr_warning("unknown stat config term %" PRI_lu64 "\n",
145                                    event->data[i].tag);
146                 }
147         }
148 }
149
150 size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp)
151 {
152         const char *s;
153
154         if (event->header.misc & PERF_RECORD_MISC_COMM_EXEC)
155                 s = " exec";
156         else
157                 s = "";
158
159         return fprintf(fp, "%s: %s:%d/%d\n", s, event->comm.comm, event->comm.pid, event->comm.tid);
160 }
161
162 size_t perf_event__fprintf_namespaces(union perf_event *event, FILE *fp)
163 {
164         size_t ret = 0;
165         struct perf_ns_link_info *ns_link_info;
166         u32 nr_namespaces, idx;
167
168         ns_link_info = event->namespaces.link_info;
169         nr_namespaces = event->namespaces.nr_namespaces;
170
171         ret += fprintf(fp, " %d/%d - nr_namespaces: %u\n\t\t[",
172                        event->namespaces.pid,
173                        event->namespaces.tid,
174                        nr_namespaces);
175
176         for (idx = 0; idx < nr_namespaces; idx++) {
177                 if (idx && (idx % 4 == 0))
178                         ret += fprintf(fp, "\n\t\t ");
179
180                 ret  += fprintf(fp, "%u/%s: %" PRIu64 "/%#" PRIx64 "%s", idx,
181                                 perf_ns__name(idx), (u64)ns_link_info[idx].dev,
182                                 (u64)ns_link_info[idx].ino,
183                                 ((idx + 1) != nr_namespaces) ? ", " : "]\n");
184         }
185
186         return ret;
187 }
188
189 size_t perf_event__fprintf_cgroup(union perf_event *event, FILE *fp)
190 {
191         return fprintf(fp, " cgroup: %" PRI_lu64 " %s\n",
192                        event->cgroup.id, event->cgroup.path);
193 }
194
195 int perf_event__process_comm(struct perf_tool *tool __maybe_unused,
196                              union perf_event *event,
197                              struct perf_sample *sample,
198                              struct machine *machine)
199 {
200         return machine__process_comm_event(machine, event, sample);
201 }
202
203 int perf_event__process_namespaces(struct perf_tool *tool __maybe_unused,
204                                    union perf_event *event,
205                                    struct perf_sample *sample,
206                                    struct machine *machine)
207 {
208         return machine__process_namespaces_event(machine, event, sample);
209 }
210
211 int perf_event__process_cgroup(struct perf_tool *tool __maybe_unused,
212                                union perf_event *event,
213                                struct perf_sample *sample,
214                                struct machine *machine)
215 {
216         return machine__process_cgroup_event(machine, event, sample);
217 }
218
219 int perf_event__process_lost(struct perf_tool *tool __maybe_unused,
220                              union perf_event *event,
221                              struct perf_sample *sample,
222                              struct machine *machine)
223 {
224         return machine__process_lost_event(machine, event, sample);
225 }
226
227 int perf_event__process_aux(struct perf_tool *tool __maybe_unused,
228                             union perf_event *event,
229                             struct perf_sample *sample __maybe_unused,
230                             struct machine *machine)
231 {
232         return machine__process_aux_event(machine, event);
233 }
234
235 int perf_event__process_itrace_start(struct perf_tool *tool __maybe_unused,
236                                      union perf_event *event,
237                                      struct perf_sample *sample __maybe_unused,
238                                      struct machine *machine)
239 {
240         return machine__process_itrace_start_event(machine, event);
241 }
242
243 int perf_event__process_aux_output_hw_id(struct perf_tool *tool __maybe_unused,
244                                          union perf_event *event,
245                                          struct perf_sample *sample __maybe_unused,
246                                          struct machine *machine)
247 {
248         return machine__process_aux_output_hw_id_event(machine, event);
249 }
250
251 int perf_event__process_lost_samples(struct perf_tool *tool __maybe_unused,
252                                      union perf_event *event,
253                                      struct perf_sample *sample,
254                                      struct machine *machine)
255 {
256         return machine__process_lost_samples_event(machine, event, sample);
257 }
258
259 int perf_event__process_switch(struct perf_tool *tool __maybe_unused,
260                                union perf_event *event,
261                                struct perf_sample *sample __maybe_unused,
262                                struct machine *machine)
263 {
264         return machine__process_switch_event(machine, event);
265 }
266
267 int perf_event__process_ksymbol(struct perf_tool *tool __maybe_unused,
268                                 union perf_event *event,
269                                 struct perf_sample *sample __maybe_unused,
270                                 struct machine *machine)
271 {
272         return machine__process_ksymbol(machine, event, sample);
273 }
274
275 int perf_event__process_bpf(struct perf_tool *tool __maybe_unused,
276                             union perf_event *event,
277                             struct perf_sample *sample,
278                             struct machine *machine)
279 {
280         return machine__process_bpf(machine, event, sample);
281 }
282
283 int perf_event__process_text_poke(struct perf_tool *tool __maybe_unused,
284                                   union perf_event *event,
285                                   struct perf_sample *sample,
286                                   struct machine *machine)
287 {
288         return machine__process_text_poke(machine, event, sample);
289 }
290
291 size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)
292 {
293         return fprintf(fp, " %d/%d: [%#" PRI_lx64 "(%#" PRI_lx64 ") @ %#" PRI_lx64 "]: %c %s\n",
294                        event->mmap.pid, event->mmap.tid, event->mmap.start,
295                        event->mmap.len, event->mmap.pgoff,
296                        (event->header.misc & PERF_RECORD_MISC_MMAP_DATA) ? 'r' : 'x',
297                        event->mmap.filename);
298 }
299
300 size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp)
301 {
302         if (event->header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID) {
303                 char sbuild_id[SBUILD_ID_SIZE];
304                 struct build_id bid;
305
306                 build_id__init(&bid, event->mmap2.build_id,
307                                event->mmap2.build_id_size);
308                 build_id__sprintf(&bid, sbuild_id);
309
310                 return fprintf(fp, " %d/%d: [%#" PRI_lx64 "(%#" PRI_lx64 ") @ %#" PRI_lx64
311                                    " <%s>]: %c%c%c%c %s\n",
312                                event->mmap2.pid, event->mmap2.tid, event->mmap2.start,
313                                event->mmap2.len, event->mmap2.pgoff, sbuild_id,
314                                (event->mmap2.prot & PROT_READ) ? 'r' : '-',
315                                (event->mmap2.prot & PROT_WRITE) ? 'w' : '-',
316                                (event->mmap2.prot & PROT_EXEC) ? 'x' : '-',
317                                (event->mmap2.flags & MAP_SHARED) ? 's' : 'p',
318                                event->mmap2.filename);
319         } else {
320                 return fprintf(fp, " %d/%d: [%#" PRI_lx64 "(%#" PRI_lx64 ") @ %#" PRI_lx64
321                                    " %02x:%02x %"PRI_lu64" %"PRI_lu64"]: %c%c%c%c %s\n",
322                                event->mmap2.pid, event->mmap2.tid, event->mmap2.start,
323                                event->mmap2.len, event->mmap2.pgoff, event->mmap2.maj,
324                                event->mmap2.min, event->mmap2.ino,
325                                event->mmap2.ino_generation,
326                                (event->mmap2.prot & PROT_READ) ? 'r' : '-',
327                                (event->mmap2.prot & PROT_WRITE) ? 'w' : '-',
328                                (event->mmap2.prot & PROT_EXEC) ? 'x' : '-',
329                                (event->mmap2.flags & MAP_SHARED) ? 's' : 'p',
330                                event->mmap2.filename);
331         }
332 }
333
334 size_t perf_event__fprintf_thread_map(union perf_event *event, FILE *fp)
335 {
336         struct perf_thread_map *threads = thread_map__new_event(&event->thread_map);
337         size_t ret;
338
339         ret = fprintf(fp, " nr: ");
340
341         if (threads)
342                 ret += thread_map__fprintf(threads, fp);
343         else
344                 ret += fprintf(fp, "failed to get threads from event\n");
345
346         perf_thread_map__put(threads);
347         return ret;
348 }
349
350 size_t perf_event__fprintf_cpu_map(union perf_event *event, FILE *fp)
351 {
352         struct perf_cpu_map *cpus = cpu_map__new_data(&event->cpu_map.data);
353         size_t ret;
354
355         ret = fprintf(fp, ": ");
356
357         if (cpus)
358                 ret += cpu_map__fprintf(cpus, fp);
359         else
360                 ret += fprintf(fp, "failed to get cpumap from event\n");
361
362         perf_cpu_map__put(cpus);
363         return ret;
364 }
365
366 int perf_event__process_mmap(struct perf_tool *tool __maybe_unused,
367                              union perf_event *event,
368                              struct perf_sample *sample,
369                              struct machine *machine)
370 {
371         return machine__process_mmap_event(machine, event, sample);
372 }
373
374 int perf_event__process_mmap2(struct perf_tool *tool __maybe_unused,
375                              union perf_event *event,
376                              struct perf_sample *sample,
377                              struct machine *machine)
378 {
379         return machine__process_mmap2_event(machine, event, sample);
380 }
381
382 size_t perf_event__fprintf_task(union perf_event *event, FILE *fp)
383 {
384         return fprintf(fp, "(%d:%d):(%d:%d)\n",
385                        event->fork.pid, event->fork.tid,
386                        event->fork.ppid, event->fork.ptid);
387 }
388
389 int perf_event__process_fork(struct perf_tool *tool __maybe_unused,
390                              union perf_event *event,
391                              struct perf_sample *sample,
392                              struct machine *machine)
393 {
394         return machine__process_fork_event(machine, event, sample);
395 }
396
397 int perf_event__process_exit(struct perf_tool *tool __maybe_unused,
398                              union perf_event *event,
399                              struct perf_sample *sample,
400                              struct machine *machine)
401 {
402         return machine__process_exit_event(machine, event, sample);
403 }
404
405 size_t perf_event__fprintf_aux(union perf_event *event, FILE *fp)
406 {
407         return fprintf(fp, " offset: %#"PRI_lx64" size: %#"PRI_lx64" flags: %#"PRI_lx64" [%s%s%s]\n",
408                        event->aux.aux_offset, event->aux.aux_size,
409                        event->aux.flags,
410                        event->aux.flags & PERF_AUX_FLAG_TRUNCATED ? "T" : "",
411                        event->aux.flags & PERF_AUX_FLAG_OVERWRITE ? "O" : "",
412                        event->aux.flags & PERF_AUX_FLAG_PARTIAL   ? "P" : "");
413 }
414
415 size_t perf_event__fprintf_itrace_start(union perf_event *event, FILE *fp)
416 {
417         return fprintf(fp, " pid: %u tid: %u\n",
418                        event->itrace_start.pid, event->itrace_start.tid);
419 }
420
421 size_t perf_event__fprintf_aux_output_hw_id(union perf_event *event, FILE *fp)
422 {
423         return fprintf(fp, " hw_id: %#"PRI_lx64"\n",
424                        event->aux_output_hw_id.hw_id);
425 }
426
427 size_t perf_event__fprintf_switch(union perf_event *event, FILE *fp)
428 {
429         bool out = event->header.misc & PERF_RECORD_MISC_SWITCH_OUT;
430         const char *in_out = !out ? "IN         " :
431                 !(event->header.misc & PERF_RECORD_MISC_SWITCH_OUT_PREEMPT) ?
432                                     "OUT        " : "OUT preempt";
433
434         if (event->header.type == PERF_RECORD_SWITCH)
435                 return fprintf(fp, " %s\n", in_out);
436
437         return fprintf(fp, " %s  %s pid/tid: %5d/%-5d\n",
438                        in_out, out ? "next" : "prev",
439                        event->context_switch.next_prev_pid,
440                        event->context_switch.next_prev_tid);
441 }
442
443 static size_t perf_event__fprintf_lost(union perf_event *event, FILE *fp)
444 {
445         return fprintf(fp, " lost %" PRI_lu64 "\n", event->lost.lost);
446 }
447
448 size_t perf_event__fprintf_ksymbol(union perf_event *event, FILE *fp)
449 {
450         return fprintf(fp, " addr %" PRI_lx64 " len %u type %u flags 0x%x name %s\n",
451                        event->ksymbol.addr, event->ksymbol.len,
452                        event->ksymbol.ksym_type,
453                        event->ksymbol.flags, event->ksymbol.name);
454 }
455
456 size_t perf_event__fprintf_bpf(union perf_event *event, FILE *fp)
457 {
458         return fprintf(fp, " type %u, flags %u, id %u\n",
459                        event->bpf.type, event->bpf.flags, event->bpf.id);
460 }
461
462 static int text_poke_printer(enum binary_printer_ops op, unsigned int val,
463                              void *extra, FILE *fp)
464 {
465         bool old = *(bool *)extra;
466
467         switch ((int)op) {
468         case BINARY_PRINT_LINE_BEGIN:
469                 return fprintf(fp, "            %s bytes:", old ? "Old" : "New");
470         case BINARY_PRINT_NUM_DATA:
471                 return fprintf(fp, " %02x", val);
472         case BINARY_PRINT_LINE_END:
473                 return fprintf(fp, "\n");
474         default:
475                 return 0;
476         }
477 }
478
479 size_t perf_event__fprintf_text_poke(union perf_event *event, struct machine *machine, FILE *fp)
480 {
481         struct perf_record_text_poke_event *tp = &event->text_poke;
482         size_t ret;
483         bool old;
484
485         ret = fprintf(fp, " %" PRI_lx64 " ", tp->addr);
486         if (machine) {
487                 struct addr_location al;
488
489                 addr_location__init(&al);
490                 al.map = map__get(maps__find(machine__kernel_maps(machine), tp->addr));
491                 if (al.map && map__load(al.map) >= 0) {
492                         al.addr = map__map_ip(al.map, tp->addr);
493                         al.sym = map__find_symbol(al.map, al.addr);
494                         if (al.sym)
495                                 ret += symbol__fprintf_symname_offs(al.sym, &al, fp);
496                 }
497                 addr_location__exit(&al);
498         }
499         ret += fprintf(fp, " old len %u new len %u\n", tp->old_len, tp->new_len);
500         old = true;
501         ret += binary__fprintf(tp->bytes, tp->old_len, 16, text_poke_printer,
502                                &old, fp);
503         old = false;
504         ret += binary__fprintf(tp->bytes + tp->old_len, tp->new_len, 16,
505                                text_poke_printer, &old, fp);
506         return ret;
507 }
508
509 size_t perf_event__fprintf(union perf_event *event, struct machine *machine, FILE *fp)
510 {
511         size_t ret = fprintf(fp, "PERF_RECORD_%s",
512                              perf_event__name(event->header.type));
513
514         switch (event->header.type) {
515         case PERF_RECORD_COMM:
516                 ret += perf_event__fprintf_comm(event, fp);
517                 break;
518         case PERF_RECORD_FORK:
519         case PERF_RECORD_EXIT:
520                 ret += perf_event__fprintf_task(event, fp);
521                 break;
522         case PERF_RECORD_MMAP:
523                 ret += perf_event__fprintf_mmap(event, fp);
524                 break;
525         case PERF_RECORD_NAMESPACES:
526                 ret += perf_event__fprintf_namespaces(event, fp);
527                 break;
528         case PERF_RECORD_CGROUP:
529                 ret += perf_event__fprintf_cgroup(event, fp);
530                 break;
531         case PERF_RECORD_MMAP2:
532                 ret += perf_event__fprintf_mmap2(event, fp);
533                 break;
534         case PERF_RECORD_AUX:
535                 ret += perf_event__fprintf_aux(event, fp);
536                 break;
537         case PERF_RECORD_ITRACE_START:
538                 ret += perf_event__fprintf_itrace_start(event, fp);
539                 break;
540         case PERF_RECORD_SWITCH:
541         case PERF_RECORD_SWITCH_CPU_WIDE:
542                 ret += perf_event__fprintf_switch(event, fp);
543                 break;
544         case PERF_RECORD_LOST:
545                 ret += perf_event__fprintf_lost(event, fp);
546                 break;
547         case PERF_RECORD_KSYMBOL:
548                 ret += perf_event__fprintf_ksymbol(event, fp);
549                 break;
550         case PERF_RECORD_BPF_EVENT:
551                 ret += perf_event__fprintf_bpf(event, fp);
552                 break;
553         case PERF_RECORD_TEXT_POKE:
554                 ret += perf_event__fprintf_text_poke(event, machine, fp);
555                 break;
556         case PERF_RECORD_AUX_OUTPUT_HW_ID:
557                 ret += perf_event__fprintf_aux_output_hw_id(event, fp);
558                 break;
559         default:
560                 ret += fprintf(fp, "\n");
561         }
562
563         return ret;
564 }
565
566 int perf_event__process(struct perf_tool *tool __maybe_unused,
567                         union perf_event *event,
568                         struct perf_sample *sample,
569                         struct machine *machine)
570 {
571         return machine__process_event(machine, event, sample);
572 }
573
574 struct map *thread__find_map(struct thread *thread, u8 cpumode, u64 addr,
575                              struct addr_location *al)
576 {
577         struct maps *maps = thread__maps(thread);
578         struct machine *machine = maps__machine(maps);
579         bool load_map = false;
580
581         maps__zput(al->maps);
582         map__zput(al->map);
583         thread__zput(al->thread);
584         al->thread = thread__get(thread);
585
586         al->addr = addr;
587         al->cpumode = cpumode;
588         al->filtered = 0;
589
590         if (machine == NULL)
591                 return NULL;
592
593         if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) {
594                 al->level = 'k';
595                 maps = machine__kernel_maps(machine);
596                 load_map = true;
597         } else if (cpumode == PERF_RECORD_MISC_USER && perf_host) {
598                 al->level = '.';
599         } else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) {
600                 al->level = 'g';
601                 maps = machine__kernel_maps(machine);
602                 load_map = true;
603         } else if (cpumode == PERF_RECORD_MISC_GUEST_USER && perf_guest) {
604                 al->level = 'u';
605         } else {
606                 al->level = 'H';
607
608                 if ((cpumode == PERF_RECORD_MISC_GUEST_USER ||
609                         cpumode == PERF_RECORD_MISC_GUEST_KERNEL) &&
610                         !perf_guest)
611                         al->filtered |= (1 << HIST_FILTER__GUEST);
612                 if ((cpumode == PERF_RECORD_MISC_USER ||
613                         cpumode == PERF_RECORD_MISC_KERNEL) &&
614                         !perf_host)
615                         al->filtered |= (1 << HIST_FILTER__HOST);
616
617                 return NULL;
618         }
619         al->maps = maps__get(maps);
620         al->map = map__get(maps__find(maps, al->addr));
621         if (al->map != NULL) {
622                 /*
623                  * Kernel maps might be changed when loading symbols so loading
624                  * must be done prior to using kernel maps.
625                  */
626                 if (load_map)
627                         map__load(al->map);
628                 al->addr = map__map_ip(al->map, al->addr);
629         }
630
631         return al->map;
632 }
633
634 /*
635  * For branch stacks or branch samples, the sample cpumode might not be correct
636  * because it applies only to the sample 'ip' and not necessary to 'addr' or
637  * branch stack addresses. If possible, use a fallback to deal with those cases.
638  */
639 struct map *thread__find_map_fb(struct thread *thread, u8 cpumode, u64 addr,
640                                 struct addr_location *al)
641 {
642         struct map *map = thread__find_map(thread, cpumode, addr, al);
643         struct machine *machine = maps__machine(thread__maps(thread));
644         u8 addr_cpumode = machine__addr_cpumode(machine, cpumode, addr);
645
646         if (map || addr_cpumode == cpumode)
647                 return map;
648
649         return thread__find_map(thread, addr_cpumode, addr, al);
650 }
651
652 struct symbol *thread__find_symbol(struct thread *thread, u8 cpumode,
653                                    u64 addr, struct addr_location *al)
654 {
655         al->sym = NULL;
656         if (thread__find_map(thread, cpumode, addr, al))
657                 al->sym = map__find_symbol(al->map, al->addr);
658         return al->sym;
659 }
660
661 struct symbol *thread__find_symbol_fb(struct thread *thread, u8 cpumode,
662                                       u64 addr, struct addr_location *al)
663 {
664         al->sym = NULL;
665         if (thread__find_map_fb(thread, cpumode, addr, al))
666                 al->sym = map__find_symbol(al->map, al->addr);
667         return al->sym;
668 }
669
670 static bool check_address_range(struct intlist *addr_list, int addr_range,
671                                 unsigned long addr)
672 {
673         struct int_node *pos;
674
675         intlist__for_each_entry(pos, addr_list) {
676                 if (addr >= pos->i && addr < pos->i + addr_range)
677                         return true;
678         }
679
680         return false;
681 }
682
683 /*
684  * Callers need to drop the reference to al->thread, obtained in
685  * machine__findnew_thread()
686  */
687 int machine__resolve(struct machine *machine, struct addr_location *al,
688                      struct perf_sample *sample)
689 {
690         struct thread *thread;
691         struct dso *dso;
692
693         if (symbol_conf.guest_code && !machine__is_host(machine))
694                 thread = machine__findnew_guest_code(machine, sample->pid);
695         else
696                 thread = machine__findnew_thread(machine, sample->pid, sample->tid);
697         if (thread == NULL)
698                 return -1;
699
700         dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread__tid(thread));
701         thread__find_map(thread, sample->cpumode, sample->ip, al);
702         dso = al->map ? map__dso(al->map) : NULL;
703         dump_printf(" ...... dso: %s\n",
704                 dso
705                 ? dso->long_name
706                 : (al->level == 'H' ? "[hypervisor]" : "<not found>"));
707
708         if (thread__is_filtered(thread))
709                 al->filtered |= (1 << HIST_FILTER__THREAD);
710
711         thread__put(thread);
712         thread = NULL;
713
714         al->sym = NULL;
715         al->cpu = sample->cpu;
716         al->socket = -1;
717         al->srcline = NULL;
718
719         if (al->cpu >= 0) {
720                 struct perf_env *env = machine->env;
721
722                 if (env && env->cpu)
723                         al->socket = env->cpu[al->cpu].socket_id;
724         }
725
726         if (al->map) {
727                 if (symbol_conf.dso_list &&
728                     (!dso || !(strlist__has_entry(symbol_conf.dso_list,
729                                                   dso->short_name) ||
730                                (dso->short_name != dso->long_name &&
731                                 strlist__has_entry(symbol_conf.dso_list,
732                                                    dso->long_name))))) {
733                         al->filtered |= (1 << HIST_FILTER__DSO);
734                 }
735
736                 al->sym = map__find_symbol(al->map, al->addr);
737         } else if (symbol_conf.dso_list) {
738                 al->filtered |= (1 << HIST_FILTER__DSO);
739         }
740
741         if (symbol_conf.sym_list) {
742                 int ret = 0;
743                 char al_addr_str[32];
744                 size_t sz = sizeof(al_addr_str);
745
746                 if (al->sym) {
747                         ret = strlist__has_entry(symbol_conf.sym_list,
748                                                 al->sym->name);
749                 }
750                 if (!ret && al->sym) {
751                         snprintf(al_addr_str, sz, "0x%"PRIx64,
752                                  map__unmap_ip(al->map, al->sym->start));
753                         ret = strlist__has_entry(symbol_conf.sym_list,
754                                                 al_addr_str);
755                 }
756                 if (!ret && symbol_conf.addr_list && al->map) {
757                         unsigned long addr = map__unmap_ip(al->map, al->addr);
758
759                         ret = intlist__has_entry(symbol_conf.addr_list, addr);
760                         if (!ret && symbol_conf.addr_range) {
761                                 ret = check_address_range(symbol_conf.addr_list,
762                                                           symbol_conf.addr_range,
763                                                           addr);
764                         }
765                 }
766
767                 if (!ret)
768                         al->filtered |= (1 << HIST_FILTER__SYMBOL);
769         }
770
771         return 0;
772 }
773
774 bool is_bts_event(struct perf_event_attr *attr)
775 {
776         return attr->type == PERF_TYPE_HARDWARE &&
777                (attr->config & PERF_COUNT_HW_BRANCH_INSTRUCTIONS) &&
778                attr->sample_period == 1;
779 }
780
781 bool sample_addr_correlates_sym(struct perf_event_attr *attr)
782 {
783         if (attr->type == PERF_TYPE_SOFTWARE &&
784             (attr->config == PERF_COUNT_SW_PAGE_FAULTS ||
785              attr->config == PERF_COUNT_SW_PAGE_FAULTS_MIN ||
786              attr->config == PERF_COUNT_SW_PAGE_FAULTS_MAJ))
787                 return true;
788
789         if (is_bts_event(attr))
790                 return true;
791
792         return false;
793 }
794
795 void thread__resolve(struct thread *thread, struct addr_location *al,
796                      struct perf_sample *sample)
797 {
798         thread__find_map_fb(thread, sample->cpumode, sample->addr, al);
799
800         al->cpu = sample->cpu;
801         al->sym = NULL;
802
803         if (al->map)
804                 al->sym = map__find_symbol(al->map, al->addr);
805 }
This page took 0.083954 seconds and 4 git commands to generate.