.. | .. |
---|
2 | 2 | #include <sys/sysmacros.h> |
---|
3 | 3 | #include <sys/types.h> |
---|
4 | 4 | #include <errno.h> |
---|
| 5 | +#include <libgen.h> |
---|
5 | 6 | #include <stdio.h> |
---|
6 | 7 | #include <stdlib.h> |
---|
7 | 8 | #include <string.h> |
---|
.. | .. |
---|
13 | 14 | #include <sys/mman.h> |
---|
14 | 15 | #include <linux/stringify.h> |
---|
15 | 16 | |
---|
16 | | -#include "util.h" |
---|
| 17 | +#include "build-id.h" |
---|
17 | 18 | #include "event.h" |
---|
18 | 19 | #include "debug.h" |
---|
19 | 20 | #include "evlist.h" |
---|
.. | .. |
---|
25 | 26 | #include "jit.h" |
---|
26 | 27 | #include "jitdump.h" |
---|
27 | 28 | #include "genelf.h" |
---|
28 | | -#include "../builtin.h" |
---|
| 29 | +#include "thread.h" |
---|
29 | 30 | |
---|
30 | | -#include "sane_ctype.h" |
---|
| 31 | +#include <linux/ctype.h> |
---|
| 32 | +#include <linux/zalloc.h> |
---|
31 | 33 | |
---|
32 | 34 | struct jit_buf_desc { |
---|
33 | 35 | struct perf_data *output; |
---|
.. | .. |
---|
38 | 40 | uint64_t sample_type; |
---|
39 | 41 | size_t bufsize; |
---|
40 | 42 | FILE *in; |
---|
41 | | - bool needs_bswap; /* handles cross-endianess */ |
---|
| 43 | + bool needs_bswap; /* handles cross-endianness */ |
---|
42 | 44 | bool use_arch_timestamp; |
---|
43 | 45 | void *debug_data; |
---|
44 | 46 | void *unwinding_data; |
---|
.. | .. |
---|
56 | 58 | unsigned long vma; |
---|
57 | 59 | unsigned int lineno; |
---|
58 | 60 | /* The filename format is unspecified, absolute path, relative etc. */ |
---|
59 | | - char const filename[0]; |
---|
| 61 | + char const filename[]; |
---|
60 | 62 | }; |
---|
61 | 63 | |
---|
62 | 64 | struct jit_tool { |
---|
.. | .. |
---|
116 | 118 | static int |
---|
117 | 119 | jit_validate_events(struct perf_session *session) |
---|
118 | 120 | { |
---|
119 | | - struct perf_evsel *evsel; |
---|
| 121 | + struct evsel *evsel; |
---|
120 | 122 | |
---|
121 | 123 | /* |
---|
122 | 124 | * check that all events use CLOCK_MONOTONIC |
---|
123 | 125 | */ |
---|
124 | 126 | evlist__for_each_entry(session->evlist, evsel) { |
---|
125 | | - if (evsel->attr.use_clockid == 0 || evsel->attr.clockid != CLOCK_MONOTONIC) |
---|
| 127 | + if (evsel->core.attr.use_clockid == 0 || evsel->core.attr.clockid != CLOCK_MONOTONIC) |
---|
126 | 128 | return -1; |
---|
127 | 129 | } |
---|
128 | 130 | return 0; |
---|
.. | .. |
---|
367 | 369 | |
---|
368 | 370 | static uint64_t convert_timestamp(struct jit_buf_desc *jd, uint64_t timestamp) |
---|
369 | 371 | { |
---|
370 | | - struct perf_tsc_conversion tc; |
---|
| 372 | + struct perf_tsc_conversion tc = { .time_shift = 0, }; |
---|
| 373 | + struct perf_record_time_conv *time_conv = &jd->session->time_conv; |
---|
371 | 374 | |
---|
372 | 375 | if (!jd->use_arch_timestamp) |
---|
373 | 376 | return timestamp; |
---|
374 | 377 | |
---|
375 | | - tc.time_shift = jd->session->time_conv.time_shift; |
---|
376 | | - tc.time_mult = jd->session->time_conv.time_mult; |
---|
377 | | - tc.time_zero = jd->session->time_conv.time_zero; |
---|
| 378 | + tc.time_shift = time_conv->time_shift; |
---|
| 379 | + tc.time_mult = time_conv->time_mult; |
---|
| 380 | + tc.time_zero = time_conv->time_zero; |
---|
378 | 381 | |
---|
379 | | - if (!tc.time_mult) |
---|
380 | | - return 0; |
---|
| 382 | + /* |
---|
| 383 | + * The event TIME_CONV was extended for the fields from "time_cycles" |
---|
| 384 | + * when supported cap_user_time_short, for backward compatibility, |
---|
| 385 | + * checks the event size and assigns these extended fields if these |
---|
| 386 | + * fields are contained in the event. |
---|
| 387 | + */ |
---|
| 388 | + if (event_contains(*time_conv, time_cycles)) { |
---|
| 389 | + tc.time_cycles = time_conv->time_cycles; |
---|
| 390 | + tc.time_mask = time_conv->time_mask; |
---|
| 391 | + tc.cap_user_time_zero = time_conv->cap_user_time_zero; |
---|
| 392 | + tc.cap_user_time_short = time_conv->cap_user_time_short; |
---|
| 393 | + |
---|
| 394 | + if (!tc.cap_user_time_zero) |
---|
| 395 | + return 0; |
---|
| 396 | + } |
---|
381 | 397 | |
---|
382 | 398 | return tsc_to_perf_time(timestamp, &tc); |
---|
383 | 399 | } |
---|
.. | .. |
---|
430 | 446 | jd->unwinding_data, jd->eh_frame_hdr_size, jd->unwinding_size); |
---|
431 | 447 | |
---|
432 | 448 | if (jd->debug_data && jd->nr_debug_entries) { |
---|
433 | | - free(jd->debug_data); |
---|
434 | | - jd->debug_data = NULL; |
---|
| 449 | + zfree(&jd->debug_data); |
---|
435 | 450 | jd->nr_debug_entries = 0; |
---|
436 | 451 | } |
---|
437 | 452 | |
---|
438 | 453 | if (jd->unwinding_data && jd->eh_frame_hdr_size) { |
---|
439 | | - free(jd->unwinding_data); |
---|
440 | | - jd->unwinding_data = NULL; |
---|
| 454 | + zfree(&jd->unwinding_data); |
---|
441 | 455 | jd->eh_frame_hdr_size = 0; |
---|
442 | 456 | jd->unwinding_mapped_size = 0; |
---|
443 | 457 | jd->unwinding_size = 0; |
---|
.. | .. |
---|
750 | 764 | return 0; |
---|
751 | 765 | } |
---|
752 | 766 | |
---|
| 767 | +static void jit_add_pid(struct machine *machine, pid_t pid) |
---|
| 768 | +{ |
---|
| 769 | + struct thread *thread = machine__findnew_thread(machine, pid, pid); |
---|
| 770 | + |
---|
| 771 | + if (!thread) { |
---|
| 772 | + pr_err("%s: thread %d not found or created\n", __func__, pid); |
---|
| 773 | + return; |
---|
| 774 | + } |
---|
| 775 | + |
---|
| 776 | + thread->priv = (void *)1; |
---|
| 777 | +} |
---|
| 778 | + |
---|
| 779 | +static bool jit_has_pid(struct machine *machine, pid_t pid) |
---|
| 780 | +{ |
---|
| 781 | + struct thread *thread = machine__find_thread(machine, pid, pid); |
---|
| 782 | + |
---|
| 783 | + if (!thread) |
---|
| 784 | + return 0; |
---|
| 785 | + |
---|
| 786 | + return (bool)thread->priv; |
---|
| 787 | +} |
---|
| 788 | + |
---|
753 | 789 | int |
---|
754 | 790 | jit_process(struct perf_session *session, |
---|
755 | 791 | struct perf_data *output, |
---|
.. | .. |
---|
758 | 794 | pid_t pid, |
---|
759 | 795 | u64 *nbytes) |
---|
760 | 796 | { |
---|
761 | | - struct perf_evsel *first; |
---|
| 797 | + struct evsel *first; |
---|
762 | 798 | struct jit_buf_desc jd; |
---|
763 | 799 | int ret; |
---|
764 | 800 | |
---|
765 | 801 | /* |
---|
766 | 802 | * first, detect marker mmap (i.e., the jitdump mmap) |
---|
767 | 803 | */ |
---|
768 | | - if (jit_detect(filename, pid)) |
---|
| 804 | + if (jit_detect(filename, pid)) { |
---|
| 805 | + // Strip //anon* mmaps if we processed a jitdump for this pid |
---|
| 806 | + if (jit_has_pid(machine, pid) && (strncmp(filename, "//anon", 6) == 0)) |
---|
| 807 | + return 1; |
---|
| 808 | + |
---|
769 | 809 | return 0; |
---|
| 810 | + } |
---|
770 | 811 | |
---|
771 | 812 | memset(&jd, 0, sizeof(jd)); |
---|
772 | 813 | |
---|
.. | .. |
---|
778 | 819 | * track sample_type to compute id_all layout |
---|
779 | 820 | * perf sets the same sample type to all events as of now |
---|
780 | 821 | */ |
---|
781 | | - first = perf_evlist__first(session->evlist); |
---|
782 | | - jd.sample_type = first->attr.sample_type; |
---|
| 822 | + first = evlist__first(session->evlist); |
---|
| 823 | + jd.sample_type = first->core.attr.sample_type; |
---|
783 | 824 | |
---|
784 | 825 | *nbytes = 0; |
---|
785 | 826 | |
---|
786 | 827 | ret = jit_inject(&jd, filename); |
---|
787 | 828 | if (!ret) { |
---|
| 829 | + jit_add_pid(machine, pid); |
---|
788 | 830 | *nbytes = jd.bytes_written; |
---|
789 | 831 | ret = 1; |
---|
790 | 832 | } |
---|