4 #include <linux/kernel.h>
5 #include <linux/types.h>
6 #include <perf/cpumap.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>
23 #include "thread_map.h"
24 #include "time-utils.h"
25 #include <linux/ctype.h>
27 #include "util/namespaces.h"
29 #include "symbol/kallsyms.h"
33 #include "bpf-event.h"
34 #include "print_binary.h"
38 static const char *perf_event__names
[] = {
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_HEADER_ATTR
] = "ATTR",
61 [PERF_RECORD_HEADER_EVENT_TYPE
] = "EVENT_TYPE",
62 [PERF_RECORD_HEADER_TRACING_DATA
] = "TRACING_DATA",
63 [PERF_RECORD_HEADER_BUILD_ID
] = "BUILD_ID",
64 [PERF_RECORD_FINISHED_ROUND
] = "FINISHED_ROUND",
65 [PERF_RECORD_ID_INDEX
] = "ID_INDEX",
66 [PERF_RECORD_AUXTRACE_INFO
] = "AUXTRACE_INFO",
67 [PERF_RECORD_AUXTRACE
] = "AUXTRACE",
68 [PERF_RECORD_AUXTRACE_ERROR
] = "AUXTRACE_ERROR",
69 [PERF_RECORD_THREAD_MAP
] = "THREAD_MAP",
70 [PERF_RECORD_CPU_MAP
] = "CPU_MAP",
71 [PERF_RECORD_STAT_CONFIG
] = "STAT_CONFIG",
72 [PERF_RECORD_STAT
] = "STAT",
73 [PERF_RECORD_STAT_ROUND
] = "STAT_ROUND",
74 [PERF_RECORD_EVENT_UPDATE
] = "EVENT_UPDATE",
75 [PERF_RECORD_TIME_CONV
] = "TIME_CONV",
76 [PERF_RECORD_HEADER_FEATURE
] = "FEATURE",
77 [PERF_RECORD_COMPRESSED
] = "COMPRESSED",
80 const char *perf_event__name(unsigned int id
)
82 if (id
>= ARRAY_SIZE(perf_event__names
))
84 if (!perf_event__names
[id
])
86 return perf_event__names
[id
];
89 struct process_symbol_args
{
94 static int find_symbol_cb(void *arg
, const char *name
, char type
,
97 struct process_symbol_args
*args
= arg
;
100 * Must be a function or at least an alias, as in PARISC64, where "_text" is
101 * an 'A' to the same address as "_stext".
103 if (!(kallsyms__is_function(type
) ||
104 type
== 'A') || strcmp(name
, args
->name
))
111 int kallsyms__get_function_start(const char *kallsyms_filename
,
112 const char *symbol_name
, u64
*addr
)
114 struct process_symbol_args args
= { .name
= symbol_name
, };
116 if (kallsyms__parse(kallsyms_filename
, &args
, find_symbol_cb
) <= 0)
123 void perf_event__read_stat_config(struct perf_stat_config
*config
,
124 struct perf_record_stat_config
*event
)
128 for (i
= 0; i
< event
->nr
; i
++) {
130 switch (event
->data
[i
].tag
) {
131 #define CASE(__term, __val) \
132 case PERF_STAT_CONFIG_TERM__##__term: \
133 config->__val = event->data[i].val; \
136 CASE(AGGR_MODE
, aggr_mode
)
138 CASE(INTERVAL
, interval
)
141 pr_warning("unknown stat config term %" PRI_lu64
"\n",
147 size_t perf_event__fprintf_comm(union perf_event
*event
, FILE *fp
)
151 if (event
->header
.misc
& PERF_RECORD_MISC_COMM_EXEC
)
156 return fprintf(fp
, "%s: %s:%d/%d\n", s
, event
->comm
.comm
, event
->comm
.pid
, event
->comm
.tid
);
159 size_t perf_event__fprintf_namespaces(union perf_event
*event
, FILE *fp
)
162 struct perf_ns_link_info
*ns_link_info
;
163 u32 nr_namespaces
, idx
;
165 ns_link_info
= event
->namespaces
.link_info
;
166 nr_namespaces
= event
->namespaces
.nr_namespaces
;
168 ret
+= fprintf(fp
, " %d/%d - nr_namespaces: %u\n\t\t[",
169 event
->namespaces
.pid
,
170 event
->namespaces
.tid
,
173 for (idx
= 0; idx
< nr_namespaces
; idx
++) {
174 if (idx
&& (idx
% 4 == 0))
175 ret
+= fprintf(fp
, "\n\t\t ");
177 ret
+= fprintf(fp
, "%u/%s: %" PRIu64
"/%#" PRIx64
"%s", idx
,
178 perf_ns__name(idx
), (u64
)ns_link_info
[idx
].dev
,
179 (u64
)ns_link_info
[idx
].ino
,
180 ((idx
+ 1) != nr_namespaces
) ? ", " : "]\n");
186 size_t perf_event__fprintf_cgroup(union perf_event
*event
, FILE *fp
)
188 return fprintf(fp
, " cgroup: %" PRI_lu64
" %s\n",
189 event
->cgroup
.id
, event
->cgroup
.path
);
192 int perf_event__process_comm(struct perf_tool
*tool __maybe_unused
,
193 union perf_event
*event
,
194 struct perf_sample
*sample
,
195 struct machine
*machine
)
197 return machine__process_comm_event(machine
, event
, sample
);
200 int perf_event__process_namespaces(struct perf_tool
*tool __maybe_unused
,
201 union perf_event
*event
,
202 struct perf_sample
*sample
,
203 struct machine
*machine
)
205 return machine__process_namespaces_event(machine
, event
, sample
);
208 int perf_event__process_cgroup(struct perf_tool
*tool __maybe_unused
,
209 union perf_event
*event
,
210 struct perf_sample
*sample
,
211 struct machine
*machine
)
213 return machine__process_cgroup_event(machine
, event
, sample
);
216 int perf_event__process_lost(struct perf_tool
*tool __maybe_unused
,
217 union perf_event
*event
,
218 struct perf_sample
*sample
,
219 struct machine
*machine
)
221 return machine__process_lost_event(machine
, event
, sample
);
224 int perf_event__process_aux(struct perf_tool
*tool __maybe_unused
,
225 union perf_event
*event
,
226 struct perf_sample
*sample __maybe_unused
,
227 struct machine
*machine
)
229 return machine__process_aux_event(machine
, event
);
232 int perf_event__process_itrace_start(struct perf_tool
*tool __maybe_unused
,
233 union perf_event
*event
,
234 struct perf_sample
*sample __maybe_unused
,
235 struct machine
*machine
)
237 return machine__process_itrace_start_event(machine
, event
);
240 int perf_event__process_lost_samples(struct perf_tool
*tool __maybe_unused
,
241 union perf_event
*event
,
242 struct perf_sample
*sample
,
243 struct machine
*machine
)
245 return machine__process_lost_samples_event(machine
, event
, sample
);
248 int perf_event__process_switch(struct perf_tool
*tool __maybe_unused
,
249 union perf_event
*event
,
250 struct perf_sample
*sample __maybe_unused
,
251 struct machine
*machine
)
253 return machine__process_switch_event(machine
, event
);
256 int perf_event__process_ksymbol(struct perf_tool
*tool __maybe_unused
,
257 union perf_event
*event
,
258 struct perf_sample
*sample __maybe_unused
,
259 struct machine
*machine
)
261 return machine__process_ksymbol(machine
, event
, sample
);
264 int perf_event__process_bpf(struct perf_tool
*tool __maybe_unused
,
265 union perf_event
*event
,
266 struct perf_sample
*sample
,
267 struct machine
*machine
)
269 return machine__process_bpf(machine
, event
, sample
);
272 int perf_event__process_text_poke(struct perf_tool
*tool __maybe_unused
,
273 union perf_event
*event
,
274 struct perf_sample
*sample
,
275 struct machine
*machine
)
277 return machine__process_text_poke(machine
, event
, sample
);
280 size_t perf_event__fprintf_mmap(union perf_event
*event
, FILE *fp
)
282 return fprintf(fp
, " %d/%d: [%#" PRI_lx64
"(%#" PRI_lx64
") @ %#" PRI_lx64
"]: %c %s\n",
283 event
->mmap
.pid
, event
->mmap
.tid
, event
->mmap
.start
,
284 event
->mmap
.len
, event
->mmap
.pgoff
,
285 (event
->header
.misc
& PERF_RECORD_MISC_MMAP_DATA
) ? 'r' : 'x',
286 event
->mmap
.filename
);
289 size_t perf_event__fprintf_mmap2(union perf_event
*event
, FILE *fp
)
291 return fprintf(fp
, " %d/%d: [%#" PRI_lx64
"(%#" PRI_lx64
") @ %#" PRI_lx64
292 " %02x:%02x %"PRI_lu64
" %"PRI_lu64
"]: %c%c%c%c %s\n",
293 event
->mmap2
.pid
, event
->mmap2
.tid
, event
->mmap2
.start
,
294 event
->mmap2
.len
, event
->mmap2
.pgoff
, event
->mmap2
.maj
,
295 event
->mmap2
.min
, event
->mmap2
.ino
,
296 event
->mmap2
.ino_generation
,
297 (event
->mmap2
.prot
& PROT_READ
) ? 'r' : '-',
298 (event
->mmap2
.prot
& PROT_WRITE
) ? 'w' : '-',
299 (event
->mmap2
.prot
& PROT_EXEC
) ? 'x' : '-',
300 (event
->mmap2
.flags
& MAP_SHARED
) ? 's' : 'p',
301 event
->mmap2
.filename
);
304 size_t perf_event__fprintf_thread_map(union perf_event
*event
, FILE *fp
)
306 struct perf_thread_map
*threads
= thread_map__new_event(&event
->thread_map
);
309 ret
= fprintf(fp
, " nr: ");
312 ret
+= thread_map__fprintf(threads
, fp
);
314 ret
+= fprintf(fp
, "failed to get threads from event\n");
316 perf_thread_map__put(threads
);
320 size_t perf_event__fprintf_cpu_map(union perf_event
*event
, FILE *fp
)
322 struct perf_cpu_map
*cpus
= cpu_map__new_data(&event
->cpu_map
.data
);
325 ret
= fprintf(fp
, ": ");
328 ret
+= cpu_map__fprintf(cpus
, fp
);
330 ret
+= fprintf(fp
, "failed to get cpumap from event\n");
332 perf_cpu_map__put(cpus
);
336 int perf_event__process_mmap(struct perf_tool
*tool __maybe_unused
,
337 union perf_event
*event
,
338 struct perf_sample
*sample
,
339 struct machine
*machine
)
341 return machine__process_mmap_event(machine
, event
, sample
);
344 int perf_event__process_mmap2(struct perf_tool
*tool __maybe_unused
,
345 union perf_event
*event
,
346 struct perf_sample
*sample
,
347 struct machine
*machine
)
349 return machine__process_mmap2_event(machine
, event
, sample
);
352 size_t perf_event__fprintf_task(union perf_event
*event
, FILE *fp
)
354 return fprintf(fp
, "(%d:%d):(%d:%d)\n",
355 event
->fork
.pid
, event
->fork
.tid
,
356 event
->fork
.ppid
, event
->fork
.ptid
);
359 int perf_event__process_fork(struct perf_tool
*tool __maybe_unused
,
360 union perf_event
*event
,
361 struct perf_sample
*sample
,
362 struct machine
*machine
)
364 return machine__process_fork_event(machine
, event
, sample
);
367 int perf_event__process_exit(struct perf_tool
*tool __maybe_unused
,
368 union perf_event
*event
,
369 struct perf_sample
*sample
,
370 struct machine
*machine
)
372 return machine__process_exit_event(machine
, event
, sample
);
375 size_t perf_event__fprintf_aux(union perf_event
*event
, FILE *fp
)
377 return fprintf(fp
, " offset: %#"PRI_lx64
" size: %#"PRI_lx64
" flags: %#"PRI_lx64
" [%s%s%s]\n",
378 event
->aux
.aux_offset
, event
->aux
.aux_size
,
380 event
->aux
.flags
& PERF_AUX_FLAG_TRUNCATED
? "T" : "",
381 event
->aux
.flags
& PERF_AUX_FLAG_OVERWRITE
? "O" : "",
382 event
->aux
.flags
& PERF_AUX_FLAG_PARTIAL
? "P" : "");
385 size_t perf_event__fprintf_itrace_start(union perf_event
*event
, FILE *fp
)
387 return fprintf(fp
, " pid: %u tid: %u\n",
388 event
->itrace_start
.pid
, event
->itrace_start
.tid
);
391 size_t perf_event__fprintf_switch(union perf_event
*event
, FILE *fp
)
393 bool out
= event
->header
.misc
& PERF_RECORD_MISC_SWITCH_OUT
;
394 const char *in_out
= !out
? "IN " :
395 !(event
->header
.misc
& PERF_RECORD_MISC_SWITCH_OUT_PREEMPT
) ?
396 "OUT " : "OUT preempt";
398 if (event
->header
.type
== PERF_RECORD_SWITCH
)
399 return fprintf(fp
, " %s\n", in_out
);
401 return fprintf(fp
, " %s %s pid/tid: %5d/%-5d\n",
402 in_out
, out
? "next" : "prev",
403 event
->context_switch
.next_prev_pid
,
404 event
->context_switch
.next_prev_tid
);
407 static size_t perf_event__fprintf_lost(union perf_event
*event
, FILE *fp
)
409 return fprintf(fp
, " lost %" PRI_lu64
"\n", event
->lost
.lost
);
412 size_t perf_event__fprintf_ksymbol(union perf_event
*event
, FILE *fp
)
414 return fprintf(fp
, " addr %" PRI_lx64
" len %u type %u flags 0x%x name %s\n",
415 event
->ksymbol
.addr
, event
->ksymbol
.len
,
416 event
->ksymbol
.ksym_type
,
417 event
->ksymbol
.flags
, event
->ksymbol
.name
);
420 size_t perf_event__fprintf_bpf(union perf_event
*event
, FILE *fp
)
422 return fprintf(fp
, " type %u, flags %u, id %u\n",
423 event
->bpf
.type
, event
->bpf
.flags
, event
->bpf
.id
);
426 static int text_poke_printer(enum binary_printer_ops op
, unsigned int val
,
427 void *extra
, FILE *fp
)
429 bool old
= *(bool *)extra
;
432 case BINARY_PRINT_LINE_BEGIN
:
433 return fprintf(fp
, " %s bytes:", old
? "Old" : "New");
434 case BINARY_PRINT_NUM_DATA
:
435 return fprintf(fp
, " %02x", val
);
436 case BINARY_PRINT_LINE_END
:
437 return fprintf(fp
, "\n");
443 size_t perf_event__fprintf_text_poke(union perf_event
*event
, struct machine
*machine
, FILE *fp
)
445 struct perf_record_text_poke_event
*tp
= &event
->text_poke
;
449 ret
= fprintf(fp
, " %" PRI_lx64
" ", tp
->addr
);
451 struct addr_location al
;
453 al
.map
= maps__find(&machine
->kmaps
, tp
->addr
);
454 if (al
.map
&& map__load(al
.map
) >= 0) {
455 al
.addr
= al
.map
->map_ip(al
.map
, tp
->addr
);
456 al
.sym
= map__find_symbol(al
.map
, al
.addr
);
458 ret
+= symbol__fprintf_symname_offs(al
.sym
, &al
, fp
);
461 ret
+= fprintf(fp
, " old len %u new len %u\n", tp
->old_len
, tp
->new_len
);
463 ret
+= binary__fprintf(tp
->bytes
, tp
->old_len
, 16, text_poke_printer
,
466 ret
+= binary__fprintf(tp
->bytes
+ tp
->old_len
, tp
->new_len
, 16,
467 text_poke_printer
, &old
, fp
);
471 size_t perf_event__fprintf(union perf_event
*event
, struct machine
*machine
, FILE *fp
)
473 size_t ret
= fprintf(fp
, "PERF_RECORD_%s",
474 perf_event__name(event
->header
.type
));
476 switch (event
->header
.type
) {
477 case PERF_RECORD_COMM
:
478 ret
+= perf_event__fprintf_comm(event
, fp
);
480 case PERF_RECORD_FORK
:
481 case PERF_RECORD_EXIT
:
482 ret
+= perf_event__fprintf_task(event
, fp
);
484 case PERF_RECORD_MMAP
:
485 ret
+= perf_event__fprintf_mmap(event
, fp
);
487 case PERF_RECORD_NAMESPACES
:
488 ret
+= perf_event__fprintf_namespaces(event
, fp
);
490 case PERF_RECORD_CGROUP
:
491 ret
+= perf_event__fprintf_cgroup(event
, fp
);
493 case PERF_RECORD_MMAP2
:
494 ret
+= perf_event__fprintf_mmap2(event
, fp
);
496 case PERF_RECORD_AUX
:
497 ret
+= perf_event__fprintf_aux(event
, fp
);
499 case PERF_RECORD_ITRACE_START
:
500 ret
+= perf_event__fprintf_itrace_start(event
, fp
);
502 case PERF_RECORD_SWITCH
:
503 case PERF_RECORD_SWITCH_CPU_WIDE
:
504 ret
+= perf_event__fprintf_switch(event
, fp
);
506 case PERF_RECORD_LOST
:
507 ret
+= perf_event__fprintf_lost(event
, fp
);
509 case PERF_RECORD_KSYMBOL
:
510 ret
+= perf_event__fprintf_ksymbol(event
, fp
);
512 case PERF_RECORD_BPF_EVENT
:
513 ret
+= perf_event__fprintf_bpf(event
, fp
);
515 case PERF_RECORD_TEXT_POKE
:
516 ret
+= perf_event__fprintf_text_poke(event
, machine
, fp
);
519 ret
+= fprintf(fp
, "\n");
525 int perf_event__process(struct perf_tool
*tool __maybe_unused
,
526 union perf_event
*event
,
527 struct perf_sample
*sample
,
528 struct machine
*machine
)
530 return machine__process_event(machine
, event
, sample
);
533 struct map
*thread__find_map(struct thread
*thread
, u8 cpumode
, u64 addr
,
534 struct addr_location
*al
)
536 struct maps
*maps
= thread
->maps
;
537 struct machine
*machine
= maps
->machine
;
538 bool load_map
= false;
543 al
->cpumode
= cpumode
;
546 if (machine
== NULL
) {
551 if (cpumode
== PERF_RECORD_MISC_KERNEL
&& perf_host
) {
553 al
->maps
= maps
= &machine
->kmaps
;
555 } else if (cpumode
== PERF_RECORD_MISC_USER
&& perf_host
) {
557 } else if (cpumode
== PERF_RECORD_MISC_GUEST_KERNEL
&& perf_guest
) {
559 al
->maps
= maps
= &machine
->kmaps
;
561 } else if (cpumode
== PERF_RECORD_MISC_GUEST_USER
&& perf_guest
) {
567 if ((cpumode
== PERF_RECORD_MISC_GUEST_USER
||
568 cpumode
== PERF_RECORD_MISC_GUEST_KERNEL
) &&
570 al
->filtered
|= (1 << HIST_FILTER__GUEST
);
571 if ((cpumode
== PERF_RECORD_MISC_USER
||
572 cpumode
== PERF_RECORD_MISC_KERNEL
) &&
574 al
->filtered
|= (1 << HIST_FILTER__HOST
);
579 al
->map
= maps__find(maps
, al
->addr
);
580 if (al
->map
!= NULL
) {
582 * Kernel maps might be changed when loading symbols so loading
583 * must be done prior to using kernel maps.
587 al
->addr
= al
->map
->map_ip(al
->map
, al
->addr
);
594 * For branch stacks or branch samples, the sample cpumode might not be correct
595 * because it applies only to the sample 'ip' and not necessary to 'addr' or
596 * branch stack addresses. If possible, use a fallback to deal with those cases.
598 struct map
*thread__find_map_fb(struct thread
*thread
, u8 cpumode
, u64 addr
,
599 struct addr_location
*al
)
601 struct map
*map
= thread__find_map(thread
, cpumode
, addr
, al
);
602 struct machine
*machine
= thread
->maps
->machine
;
603 u8 addr_cpumode
= machine__addr_cpumode(machine
, cpumode
, addr
);
605 if (map
|| addr_cpumode
== cpumode
)
608 return thread__find_map(thread
, addr_cpumode
, addr
, al
);
611 struct symbol
*thread__find_symbol(struct thread
*thread
, u8 cpumode
,
612 u64 addr
, struct addr_location
*al
)
615 if (thread__find_map(thread
, cpumode
, addr
, al
))
616 al
->sym
= map__find_symbol(al
->map
, al
->addr
);
620 struct symbol
*thread__find_symbol_fb(struct thread
*thread
, u8 cpumode
,
621 u64 addr
, struct addr_location
*al
)
624 if (thread__find_map_fb(thread
, cpumode
, addr
, al
))
625 al
->sym
= map__find_symbol(al
->map
, al
->addr
);
630 * Callers need to drop the reference to al->thread, obtained in
631 * machine__findnew_thread()
633 int machine__resolve(struct machine
*machine
, struct addr_location
*al
,
634 struct perf_sample
*sample
)
636 struct thread
*thread
= machine__findnew_thread(machine
, sample
->pid
,
642 dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread
), thread
->tid
);
643 thread__find_map(thread
, sample
->cpumode
, sample
->ip
, al
);
644 dump_printf(" ...... dso: %s\n",
645 al
->map
? al
->map
->dso
->long_name
:
646 al
->level
== 'H' ? "[hypervisor]" : "<not found>");
648 if (thread__is_filtered(thread
))
649 al
->filtered
|= (1 << HIST_FILTER__THREAD
);
652 al
->cpu
= sample
->cpu
;
657 struct perf_env
*env
= machine
->env
;
660 al
->socket
= env
->cpu
[al
->cpu
].socket_id
;
664 struct dso
*dso
= al
->map
->dso
;
666 if (symbol_conf
.dso_list
&&
667 (!dso
|| !(strlist__has_entry(symbol_conf
.dso_list
,
669 (dso
->short_name
!= dso
->long_name
&&
670 strlist__has_entry(symbol_conf
.dso_list
,
671 dso
->long_name
))))) {
672 al
->filtered
|= (1 << HIST_FILTER__DSO
);
675 al
->sym
= map__find_symbol(al
->map
, al
->addr
);
678 if (symbol_conf
.sym_list
) {
680 char al_addr_str
[32];
681 size_t sz
= sizeof(al_addr_str
);
684 ret
= strlist__has_entry(symbol_conf
.sym_list
,
687 if (!ret
&& al
->sym
) {
688 snprintf(al_addr_str
, sz
, "0x%"PRIx64
,
689 al
->map
->unmap_ip(al
->map
, al
->sym
->start
));
690 ret
= strlist__has_entry(symbol_conf
.sym_list
,
694 al
->filtered
|= (1 << HIST_FILTER__SYMBOL
);
701 * The preprocess_sample method will return with reference counts for the
702 * in it, when done using (and perhaps getting ref counts if needing to
703 * keep a pointer to one of those entries) it must be paired with
704 * addr_location__put(), so that the refcounts can be decremented.
706 void addr_location__put(struct addr_location
*al
)
708 thread__zput(al
->thread
);
711 bool is_bts_event(struct perf_event_attr
*attr
)
713 return attr
->type
== PERF_TYPE_HARDWARE
&&
714 (attr
->config
& PERF_COUNT_HW_BRANCH_INSTRUCTIONS
) &&
715 attr
->sample_period
== 1;
718 bool sample_addr_correlates_sym(struct perf_event_attr
*attr
)
720 if (attr
->type
== PERF_TYPE_SOFTWARE
&&
721 (attr
->config
== PERF_COUNT_SW_PAGE_FAULTS
||
722 attr
->config
== PERF_COUNT_SW_PAGE_FAULTS_MIN
||
723 attr
->config
== PERF_COUNT_SW_PAGE_FAULTS_MAJ
))
726 if (is_bts_event(attr
))
732 void thread__resolve(struct thread
*thread
, struct addr_location
*al
,
733 struct perf_sample
*sample
)
735 thread__find_map_fb(thread
, sample
->cpumode
, sample
->addr
, al
);
737 al
->cpu
= sample
->cpu
;
741 al
->sym
= map__find_symbol(al
->map
, al
->addr
);