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_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",
82 const char *perf_event__name(unsigned int id
)
84 if (id
>= ARRAY_SIZE(perf_event__names
))
86 if (!perf_event__names
[id
])
88 return perf_event__names
[id
];
91 struct process_symbol_args
{
96 static int find_func_symbol_cb(void *arg
, const char *name
, char type
,
99 struct process_symbol_args
*args
= arg
;
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".
105 if (!(kallsyms__is_function(type
) ||
106 type
== 'A') || strcmp(name
, args
->name
))
113 static int find_any_symbol_cb(void *arg
, const char *name
,
114 char type __maybe_unused
, u64 start
)
116 struct process_symbol_args
*args
= arg
;
118 if (strcmp(name
, args
->name
))
125 int kallsyms__get_function_start(const char *kallsyms_filename
,
126 const char *symbol_name
, u64
*addr
)
128 struct process_symbol_args args
= { .name
= symbol_name
, };
130 if (kallsyms__parse(kallsyms_filename
, &args
, find_func_symbol_cb
) <= 0)
137 int kallsyms__get_symbol_start(const char *kallsyms_filename
,
138 const char *symbol_name
, u64
*addr
)
140 struct process_symbol_args args
= { .name
= symbol_name
, };
142 if (kallsyms__parse(kallsyms_filename
, &args
, find_any_symbol_cb
) <= 0)
149 void perf_event__read_stat_config(struct perf_stat_config
*config
,
150 struct perf_record_stat_config
*event
)
154 for (i
= 0; i
< event
->nr
; i
++) {
156 switch (event
->data
[i
].tag
) {
157 #define CASE(__term, __val) \
158 case PERF_STAT_CONFIG_TERM__##__term: \
159 config->__val = event->data[i].val; \
162 CASE(AGGR_MODE
, aggr_mode
)
164 CASE(INTERVAL
, interval
)
165 CASE(AGGR_LEVEL
, aggr_level
)
168 pr_warning("unknown stat config term %" PRI_lu64
"\n",
174 size_t perf_event__fprintf_comm(union perf_event
*event
, FILE *fp
)
178 if (event
->header
.misc
& PERF_RECORD_MISC_COMM_EXEC
)
183 return fprintf(fp
, "%s: %s:%d/%d\n", s
, event
->comm
.comm
, event
->comm
.pid
, event
->comm
.tid
);
186 size_t perf_event__fprintf_namespaces(union perf_event
*event
, FILE *fp
)
189 struct perf_ns_link_info
*ns_link_info
;
190 u32 nr_namespaces
, idx
;
192 ns_link_info
= event
->namespaces
.link_info
;
193 nr_namespaces
= event
->namespaces
.nr_namespaces
;
195 ret
+= fprintf(fp
, " %d/%d - nr_namespaces: %u\n\t\t[",
196 event
->namespaces
.pid
,
197 event
->namespaces
.tid
,
200 for (idx
= 0; idx
< nr_namespaces
; idx
++) {
201 if (idx
&& (idx
% 4 == 0))
202 ret
+= fprintf(fp
, "\n\t\t ");
204 ret
+= fprintf(fp
, "%u/%s: %" PRIu64
"/%#" PRIx64
"%s", idx
,
205 perf_ns__name(idx
), (u64
)ns_link_info
[idx
].dev
,
206 (u64
)ns_link_info
[idx
].ino
,
207 ((idx
+ 1) != nr_namespaces
) ? ", " : "]\n");
213 size_t perf_event__fprintf_cgroup(union perf_event
*event
, FILE *fp
)
215 return fprintf(fp
, " cgroup: %" PRI_lu64
" %s\n",
216 event
->cgroup
.id
, event
->cgroup
.path
);
219 int perf_event__process_comm(const struct perf_tool
*tool __maybe_unused
,
220 union perf_event
*event
,
221 struct perf_sample
*sample
,
222 struct machine
*machine
)
224 return machine__process_comm_event(machine
, event
, sample
);
227 int perf_event__process_namespaces(const struct perf_tool
*tool __maybe_unused
,
228 union perf_event
*event
,
229 struct perf_sample
*sample
,
230 struct machine
*machine
)
232 return machine__process_namespaces_event(machine
, event
, sample
);
235 int perf_event__process_cgroup(const struct perf_tool
*tool __maybe_unused
,
236 union perf_event
*event
,
237 struct perf_sample
*sample
,
238 struct machine
*machine
)
240 return machine__process_cgroup_event(machine
, event
, sample
);
243 int perf_event__process_lost(const struct perf_tool
*tool __maybe_unused
,
244 union perf_event
*event
,
245 struct perf_sample
*sample
,
246 struct machine
*machine
)
248 return machine__process_lost_event(machine
, event
, sample
);
251 int perf_event__process_aux(const struct perf_tool
*tool __maybe_unused
,
252 union perf_event
*event
,
253 struct perf_sample
*sample __maybe_unused
,
254 struct machine
*machine
)
256 return machine__process_aux_event(machine
, event
);
259 int perf_event__process_itrace_start(const struct perf_tool
*tool __maybe_unused
,
260 union perf_event
*event
,
261 struct perf_sample
*sample __maybe_unused
,
262 struct machine
*machine
)
264 return machine__process_itrace_start_event(machine
, event
);
267 int perf_event__process_aux_output_hw_id(const struct perf_tool
*tool __maybe_unused
,
268 union perf_event
*event
,
269 struct perf_sample
*sample __maybe_unused
,
270 struct machine
*machine
)
272 return machine__process_aux_output_hw_id_event(machine
, event
);
275 int perf_event__process_lost_samples(const struct perf_tool
*tool __maybe_unused
,
276 union perf_event
*event
,
277 struct perf_sample
*sample
,
278 struct machine
*machine
)
280 return machine__process_lost_samples_event(machine
, event
, sample
);
283 int perf_event__process_switch(const struct perf_tool
*tool __maybe_unused
,
284 union perf_event
*event
,
285 struct perf_sample
*sample __maybe_unused
,
286 struct machine
*machine
)
288 return machine__process_switch_event(machine
, event
);
291 int perf_event__process_ksymbol(const struct perf_tool
*tool __maybe_unused
,
292 union perf_event
*event
,
293 struct perf_sample
*sample __maybe_unused
,
294 struct machine
*machine
)
296 return machine__process_ksymbol(machine
, event
, sample
);
299 int perf_event__process_bpf(const struct perf_tool
*tool __maybe_unused
,
300 union perf_event
*event
,
301 struct perf_sample
*sample
,
302 struct machine
*machine
)
304 return machine__process_bpf(machine
, event
, sample
);
307 int perf_event__process_text_poke(const struct perf_tool
*tool __maybe_unused
,
308 union perf_event
*event
,
309 struct perf_sample
*sample
,
310 struct machine
*machine
)
312 return machine__process_text_poke(machine
, event
, sample
);
315 size_t perf_event__fprintf_mmap(union perf_event
*event
, FILE *fp
)
317 return fprintf(fp
, " %d/%d: [%#" PRI_lx64
"(%#" PRI_lx64
") @ %#" PRI_lx64
"]: %c %s\n",
318 event
->mmap
.pid
, event
->mmap
.tid
, event
->mmap
.start
,
319 event
->mmap
.len
, event
->mmap
.pgoff
,
320 (event
->header
.misc
& PERF_RECORD_MISC_MMAP_DATA
) ? 'r' : 'x',
321 event
->mmap
.filename
);
324 size_t perf_event__fprintf_mmap2(union perf_event
*event
, FILE *fp
)
326 if (event
->header
.misc
& PERF_RECORD_MISC_MMAP_BUILD_ID
) {
327 char sbuild_id
[SBUILD_ID_SIZE
];
330 build_id__init(&bid
, event
->mmap2
.build_id
,
331 event
->mmap2
.build_id_size
);
332 build_id__sprintf(&bid
, sbuild_id
);
334 return fprintf(fp
, " %d/%d: [%#" PRI_lx64
"(%#" PRI_lx64
") @ %#" PRI_lx64
335 " <%s>]: %c%c%c%c %s\n",
336 event
->mmap2
.pid
, event
->mmap2
.tid
, event
->mmap2
.start
,
337 event
->mmap2
.len
, event
->mmap2
.pgoff
, sbuild_id
,
338 (event
->mmap2
.prot
& PROT_READ
) ? 'r' : '-',
339 (event
->mmap2
.prot
& PROT_WRITE
) ? 'w' : '-',
340 (event
->mmap2
.prot
& PROT_EXEC
) ? 'x' : '-',
341 (event
->mmap2
.flags
& MAP_SHARED
) ? 's' : 'p',
342 event
->mmap2
.filename
);
344 return fprintf(fp
, " %d/%d: [%#" PRI_lx64
"(%#" PRI_lx64
") @ %#" PRI_lx64
345 " %02x:%02x %"PRI_lu64
" %"PRI_lu64
"]: %c%c%c%c %s\n",
346 event
->mmap2
.pid
, event
->mmap2
.tid
, event
->mmap2
.start
,
347 event
->mmap2
.len
, event
->mmap2
.pgoff
, event
->mmap2
.maj
,
348 event
->mmap2
.min
, event
->mmap2
.ino
,
349 event
->mmap2
.ino_generation
,
350 (event
->mmap2
.prot
& PROT_READ
) ? 'r' : '-',
351 (event
->mmap2
.prot
& PROT_WRITE
) ? 'w' : '-',
352 (event
->mmap2
.prot
& PROT_EXEC
) ? 'x' : '-',
353 (event
->mmap2
.flags
& MAP_SHARED
) ? 's' : 'p',
354 event
->mmap2
.filename
);
358 size_t perf_event__fprintf_thread_map(union perf_event
*event
, FILE *fp
)
360 struct perf_thread_map
*threads
= thread_map__new_event(&event
->thread_map
);
363 ret
= fprintf(fp
, " nr: ");
366 ret
+= thread_map__fprintf(threads
, fp
);
368 ret
+= fprintf(fp
, "failed to get threads from event\n");
370 perf_thread_map__put(threads
);
374 size_t perf_event__fprintf_cpu_map(union perf_event
*event
, FILE *fp
)
376 struct perf_cpu_map
*cpus
= cpu_map__new_data(&event
->cpu_map
.data
);
379 ret
= fprintf(fp
, ": ");
382 ret
+= cpu_map__fprintf(cpus
, fp
);
384 ret
+= fprintf(fp
, "failed to get cpumap from event\n");
386 perf_cpu_map__put(cpus
);
390 int perf_event__process_mmap(const struct perf_tool
*tool __maybe_unused
,
391 union perf_event
*event
,
392 struct perf_sample
*sample
,
393 struct machine
*machine
)
395 return machine__process_mmap_event(machine
, event
, sample
);
398 int perf_event__process_mmap2(const struct perf_tool
*tool __maybe_unused
,
399 union perf_event
*event
,
400 struct perf_sample
*sample
,
401 struct machine
*machine
)
403 return machine__process_mmap2_event(machine
, event
, sample
);
406 size_t perf_event__fprintf_task(union perf_event
*event
, FILE *fp
)
408 return fprintf(fp
, "(%d:%d):(%d:%d)\n",
409 event
->fork
.pid
, event
->fork
.tid
,
410 event
->fork
.ppid
, event
->fork
.ptid
);
413 int perf_event__process_fork(const struct perf_tool
*tool __maybe_unused
,
414 union perf_event
*event
,
415 struct perf_sample
*sample
,
416 struct machine
*machine
)
418 return machine__process_fork_event(machine
, event
, sample
);
421 int perf_event__process_exit(const struct perf_tool
*tool __maybe_unused
,
422 union perf_event
*event
,
423 struct perf_sample
*sample
,
424 struct machine
*machine
)
426 return machine__process_exit_event(machine
, event
, sample
);
429 int perf_event__exit_del_thread(const struct perf_tool
*tool __maybe_unused
,
430 union perf_event
*event
,
431 struct perf_sample
*sample __maybe_unused
,
432 struct machine
*machine
)
434 struct thread
*thread
= machine__findnew_thread(machine
,
438 dump_printf("(%d:%d):(%d:%d)\n", event
->fork
.pid
, event
->fork
.tid
,
439 event
->fork
.ppid
, event
->fork
.ptid
);
442 machine__remove_thread(machine
, thread
);
449 size_t perf_event__fprintf_aux(union perf_event
*event
, FILE *fp
)
451 return fprintf(fp
, " offset: %#"PRI_lx64
" size: %#"PRI_lx64
" flags: %#"PRI_lx64
" [%s%s%s]\n",
452 event
->aux
.aux_offset
, event
->aux
.aux_size
,
454 event
->aux
.flags
& PERF_AUX_FLAG_TRUNCATED
? "T" : "",
455 event
->aux
.flags
& PERF_AUX_FLAG_OVERWRITE
? "O" : "",
456 event
->aux
.flags
& PERF_AUX_FLAG_PARTIAL
? "P" : "");
459 size_t perf_event__fprintf_itrace_start(union perf_event
*event
, FILE *fp
)
461 return fprintf(fp
, " pid: %u tid: %u\n",
462 event
->itrace_start
.pid
, event
->itrace_start
.tid
);
465 size_t perf_event__fprintf_aux_output_hw_id(union perf_event
*event
, FILE *fp
)
467 return fprintf(fp
, " hw_id: %#"PRI_lx64
"\n",
468 event
->aux_output_hw_id
.hw_id
);
471 size_t perf_event__fprintf_switch(union perf_event
*event
, FILE *fp
)
473 bool out
= event
->header
.misc
& PERF_RECORD_MISC_SWITCH_OUT
;
474 const char *in_out
= !out
? "IN " :
475 !(event
->header
.misc
& PERF_RECORD_MISC_SWITCH_OUT_PREEMPT
) ?
476 "OUT " : "OUT preempt";
478 if (event
->header
.type
== PERF_RECORD_SWITCH
)
479 return fprintf(fp
, " %s\n", in_out
);
481 return fprintf(fp
, " %s %s pid/tid: %5d/%-5d\n",
482 in_out
, out
? "next" : "prev",
483 event
->context_switch
.next_prev_pid
,
484 event
->context_switch
.next_prev_tid
);
487 static size_t perf_event__fprintf_lost(union perf_event
*event
, FILE *fp
)
489 return fprintf(fp
, " lost %" PRI_lu64
"\n", event
->lost
.lost
);
492 size_t perf_event__fprintf_ksymbol(union perf_event
*event
, FILE *fp
)
494 return fprintf(fp
, " addr %" PRI_lx64
" len %u type %u flags 0x%x name %s\n",
495 event
->ksymbol
.addr
, event
->ksymbol
.len
,
496 event
->ksymbol
.ksym_type
,
497 event
->ksymbol
.flags
, event
->ksymbol
.name
);
500 size_t perf_event__fprintf_bpf(union perf_event
*event
, FILE *fp
)
502 return fprintf(fp
, " type %u, flags %u, id %u\n",
503 event
->bpf
.type
, event
->bpf
.flags
, event
->bpf
.id
);
506 static int text_poke_printer(enum binary_printer_ops op
, unsigned int val
,
507 void *extra
, FILE *fp
)
509 bool old
= *(bool *)extra
;
512 case BINARY_PRINT_LINE_BEGIN
:
513 return fprintf(fp
, " %s bytes:", old
? "Old" : "New");
514 case BINARY_PRINT_NUM_DATA
:
515 return fprintf(fp
, " %02x", val
);
516 case BINARY_PRINT_LINE_END
:
517 return fprintf(fp
, "\n");
523 size_t perf_event__fprintf_text_poke(union perf_event
*event
, struct machine
*machine
, FILE *fp
)
525 struct perf_record_text_poke_event
*tp
= &event
->text_poke
;
529 ret
= fprintf(fp
, " %" PRI_lx64
" ", tp
->addr
);
531 struct addr_location al
;
533 addr_location__init(&al
);
534 al
.map
= maps__find(machine__kernel_maps(machine
), tp
->addr
);
535 if (al
.map
&& map__load(al
.map
) >= 0) {
536 al
.addr
= map__map_ip(al
.map
, tp
->addr
);
537 al
.sym
= map__find_symbol(al
.map
, al
.addr
);
539 ret
+= symbol__fprintf_symname_offs(al
.sym
, &al
, fp
);
541 addr_location__exit(&al
);
543 ret
+= fprintf(fp
, " old len %u new len %u\n", tp
->old_len
, tp
->new_len
);
545 ret
+= binary__fprintf(tp
->bytes
, tp
->old_len
, 16, text_poke_printer
,
548 ret
+= binary__fprintf(tp
->bytes
+ tp
->old_len
, tp
->new_len
, 16,
549 text_poke_printer
, &old
, fp
);
553 size_t perf_event__fprintf(union perf_event
*event
, struct machine
*machine
, FILE *fp
)
555 size_t ret
= fprintf(fp
, "PERF_RECORD_%s",
556 perf_event__name(event
->header
.type
));
558 switch (event
->header
.type
) {
559 case PERF_RECORD_COMM
:
560 ret
+= perf_event__fprintf_comm(event
, fp
);
562 case PERF_RECORD_FORK
:
563 case PERF_RECORD_EXIT
:
564 ret
+= perf_event__fprintf_task(event
, fp
);
566 case PERF_RECORD_MMAP
:
567 ret
+= perf_event__fprintf_mmap(event
, fp
);
569 case PERF_RECORD_NAMESPACES
:
570 ret
+= perf_event__fprintf_namespaces(event
, fp
);
572 case PERF_RECORD_CGROUP
:
573 ret
+= perf_event__fprintf_cgroup(event
, fp
);
575 case PERF_RECORD_MMAP2
:
576 ret
+= perf_event__fprintf_mmap2(event
, fp
);
578 case PERF_RECORD_AUX
:
579 ret
+= perf_event__fprintf_aux(event
, fp
);
581 case PERF_RECORD_ITRACE_START
:
582 ret
+= perf_event__fprintf_itrace_start(event
, fp
);
584 case PERF_RECORD_SWITCH
:
585 case PERF_RECORD_SWITCH_CPU_WIDE
:
586 ret
+= perf_event__fprintf_switch(event
, fp
);
588 case PERF_RECORD_LOST
:
589 ret
+= perf_event__fprintf_lost(event
, fp
);
591 case PERF_RECORD_KSYMBOL
:
592 ret
+= perf_event__fprintf_ksymbol(event
, fp
);
594 case PERF_RECORD_BPF_EVENT
:
595 ret
+= perf_event__fprintf_bpf(event
, fp
);
597 case PERF_RECORD_TEXT_POKE
:
598 ret
+= perf_event__fprintf_text_poke(event
, machine
, fp
);
600 case PERF_RECORD_AUX_OUTPUT_HW_ID
:
601 ret
+= perf_event__fprintf_aux_output_hw_id(event
, fp
);
604 ret
+= fprintf(fp
, "\n");
610 int perf_event__process(const struct perf_tool
*tool __maybe_unused
,
611 union perf_event
*event
,
612 struct perf_sample
*sample
,
613 struct machine
*machine
)
615 return machine__process_event(machine
, event
, sample
);
618 struct map
*thread__find_map(struct thread
*thread
, u8 cpumode
, u64 addr
,
619 struct addr_location
*al
)
621 struct maps
*maps
= thread__maps(thread
);
622 struct machine
*machine
= maps__machine(maps
);
623 bool load_map
= false;
625 maps__zput(al
->maps
);
627 thread__zput(al
->thread
);
628 al
->thread
= thread__get(thread
);
631 al
->cpumode
= cpumode
;
637 if (cpumode
== PERF_RECORD_MISC_KERNEL
&& perf_host
) {
639 maps
= machine__kernel_maps(machine
);
640 load_map
= !symbol_conf
.lazy_load_kernel_maps
;
641 } else if (cpumode
== PERF_RECORD_MISC_USER
&& perf_host
) {
643 } else if (cpumode
== PERF_RECORD_MISC_GUEST_KERNEL
&& perf_guest
) {
645 maps
= machine__kernel_maps(machine
);
646 load_map
= !symbol_conf
.lazy_load_kernel_maps
;
647 } else if (cpumode
== PERF_RECORD_MISC_GUEST_USER
&& perf_guest
) {
652 if ((cpumode
== PERF_RECORD_MISC_GUEST_USER
||
653 cpumode
== PERF_RECORD_MISC_GUEST_KERNEL
) &&
655 al
->filtered
|= (1 << HIST_FILTER__GUEST
);
656 if ((cpumode
== PERF_RECORD_MISC_USER
||
657 cpumode
== PERF_RECORD_MISC_KERNEL
) &&
659 al
->filtered
|= (1 << HIST_FILTER__HOST
);
663 al
->maps
= maps__get(maps
);
664 al
->map
= maps__find(maps
, al
->addr
);
665 if (al
->map
!= NULL
) {
667 * Kernel maps might be changed when loading symbols so loading
668 * must be done prior to using kernel maps.
672 al
->addr
= map__map_ip(al
->map
, al
->addr
);
679 * For branch stacks or branch samples, the sample cpumode might not be correct
680 * because it applies only to the sample 'ip' and not necessary to 'addr' or
681 * branch stack addresses. If possible, use a fallback to deal with those cases.
683 struct map
*thread__find_map_fb(struct thread
*thread
, u8 cpumode
, u64 addr
,
684 struct addr_location
*al
)
686 struct map
*map
= thread__find_map(thread
, cpumode
, addr
, al
);
687 struct machine
*machine
= maps__machine(thread__maps(thread
));
688 u8 addr_cpumode
= machine__addr_cpumode(machine
, cpumode
, addr
);
690 if (map
|| addr_cpumode
== cpumode
)
693 return thread__find_map(thread
, addr_cpumode
, addr
, al
);
696 struct symbol
*thread__find_symbol(struct thread
*thread
, u8 cpumode
,
697 u64 addr
, struct addr_location
*al
)
700 if (thread__find_map(thread
, cpumode
, addr
, al
))
701 al
->sym
= map__find_symbol(al
->map
, al
->addr
);
705 struct symbol
*thread__find_symbol_fb(struct thread
*thread
, u8 cpumode
,
706 u64 addr
, struct addr_location
*al
)
709 if (thread__find_map_fb(thread
, cpumode
, addr
, al
))
710 al
->sym
= map__find_symbol(al
->map
, al
->addr
);
714 static bool check_address_range(struct intlist
*addr_list
, int addr_range
,
717 struct int_node
*pos
;
719 intlist__for_each_entry(pos
, addr_list
) {
720 if (addr
>= pos
->i
&& addr
< pos
->i
+ addr_range
)
728 * Callers need to drop the reference to al->thread, obtained in
729 * machine__findnew_thread()
731 int machine__resolve(struct machine
*machine
, struct addr_location
*al
,
732 struct perf_sample
*sample
)
734 struct thread
*thread
;
737 if (symbol_conf
.guest_code
&& !machine__is_host(machine
))
738 thread
= machine__findnew_guest_code(machine
, sample
->pid
);
740 thread
= machine__findnew_thread(machine
, sample
->pid
, sample
->tid
);
744 dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread
), thread__tid(thread
));
745 thread__find_map(thread
, sample
->cpumode
, sample
->ip
, al
);
746 dso
= al
->map
? map__dso(al
->map
) : NULL
;
747 dump_printf(" ...... dso: %s\n",
749 ? dso__long_name(dso
)
750 : (al
->level
== 'H' ? "[hypervisor]" : "<not found>"));
752 if (thread__is_filtered(thread
))
753 al
->filtered
|= (1 << HIST_FILTER__THREAD
);
759 al
->cpu
= sample
->cpu
;
764 struct perf_env
*env
= machine
->env
;
767 al
->socket
= env
->cpu
[al
->cpu
].socket_id
;
771 if (symbol_conf
.dso_list
&&
772 (!dso
|| !(strlist__has_entry(symbol_conf
.dso_list
,
773 dso__short_name(dso
)) ||
774 (dso__short_name(dso
) != dso__long_name(dso
) &&
775 strlist__has_entry(symbol_conf
.dso_list
,
776 dso__long_name(dso
)))))) {
777 al
->filtered
|= (1 << HIST_FILTER__DSO
);
780 al
->sym
= map__find_symbol(al
->map
, al
->addr
);
781 } else if (symbol_conf
.dso_list
) {
782 al
->filtered
|= (1 << HIST_FILTER__DSO
);
785 if (symbol_conf
.sym_list
) {
787 char al_addr_str
[32];
788 size_t sz
= sizeof(al_addr_str
);
791 ret
= strlist__has_entry(symbol_conf
.sym_list
,
794 if (!ret
&& al
->sym
) {
795 snprintf(al_addr_str
, sz
, "0x%"PRIx64
,
796 map__unmap_ip(al
->map
, al
->sym
->start
));
797 ret
= strlist__has_entry(symbol_conf
.sym_list
,
800 if (!ret
&& symbol_conf
.addr_list
&& al
->map
) {
801 unsigned long addr
= map__unmap_ip(al
->map
, al
->addr
);
803 ret
= intlist__has_entry(symbol_conf
.addr_list
, addr
);
804 if (!ret
&& symbol_conf
.addr_range
) {
805 ret
= check_address_range(symbol_conf
.addr_list
,
806 symbol_conf
.addr_range
,
812 al
->filtered
|= (1 << HIST_FILTER__SYMBOL
);
818 bool is_bts_event(struct perf_event_attr
*attr
)
820 return attr
->type
== PERF_TYPE_HARDWARE
&&
821 (attr
->config
& PERF_COUNT_HW_BRANCH_INSTRUCTIONS
) &&
822 attr
->sample_period
== 1;
825 bool sample_addr_correlates_sym(struct perf_event_attr
*attr
)
827 if (attr
->type
== PERF_TYPE_SOFTWARE
&&
828 (attr
->config
== PERF_COUNT_SW_PAGE_FAULTS
||
829 attr
->config
== PERF_COUNT_SW_PAGE_FAULTS_MIN
||
830 attr
->config
== PERF_COUNT_SW_PAGE_FAULTS_MAJ
))
833 if (is_bts_event(attr
))
839 void thread__resolve(struct thread
*thread
, struct addr_location
*al
,
840 struct perf_sample
*sample
)
842 thread__find_map_fb(thread
, sample
->cpumode
, sample
->addr
, al
);
844 al
->cpu
= sample
->cpu
;
848 al
->sym
= map__find_symbol(al
->map
, al
->addr
);