diff options
Diffstat (limited to 'tools/perf/util/header.c')
-rw-r--r-- | tools/perf/util/header.c | 161 |
1 files changed, 26 insertions, 135 deletions
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index a4dafbee2511..a33197a4fd21 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -25,41 +25,9 @@ | |||
25 | 25 | ||
26 | static bool no_buildid_cache = false; | 26 | static bool no_buildid_cache = false; |
27 | 27 | ||
28 | static int trace_event_count; | ||
29 | static struct perf_trace_event_type *trace_events; | ||
30 | |||
31 | static u32 header_argc; | 28 | static u32 header_argc; |
32 | static const char **header_argv; | 29 | static const char **header_argv; |
33 | 30 | ||
34 | int perf_header__push_event(u64 id, const char *name) | ||
35 | { | ||
36 | struct perf_trace_event_type *nevents; | ||
37 | |||
38 | if (strlen(name) > MAX_EVENT_NAME) | ||
39 | pr_warning("Event %s will be truncated\n", name); | ||
40 | |||
41 | nevents = realloc(trace_events, (trace_event_count + 1) * sizeof(*trace_events)); | ||
42 | if (nevents == NULL) | ||
43 | return -ENOMEM; | ||
44 | trace_events = nevents; | ||
45 | |||
46 | memset(&trace_events[trace_event_count], 0, sizeof(struct perf_trace_event_type)); | ||
47 | trace_events[trace_event_count].event_id = id; | ||
48 | strncpy(trace_events[trace_event_count].name, name, MAX_EVENT_NAME - 1); | ||
49 | trace_event_count++; | ||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | char *perf_header__find_event(u64 id) | ||
54 | { | ||
55 | int i; | ||
56 | for (i = 0 ; i < trace_event_count; i++) { | ||
57 | if (trace_events[i].event_id == id) | ||
58 | return trace_events[i].name; | ||
59 | } | ||
60 | return NULL; | ||
61 | } | ||
62 | |||
63 | /* | 31 | /* |
64 | * magic2 = "PERFILE2" | 32 | * magic2 = "PERFILE2" |
65 | * must be a numerical value to let the endianness | 33 | * must be a numerical value to let the endianness |
@@ -748,18 +716,19 @@ static int build_cpu_topo(struct cpu_topo *tp, int cpu) | |||
748 | char filename[MAXPATHLEN]; | 716 | char filename[MAXPATHLEN]; |
749 | char *buf = NULL, *p; | 717 | char *buf = NULL, *p; |
750 | size_t len = 0; | 718 | size_t len = 0; |
719 | ssize_t sret; | ||
751 | u32 i = 0; | 720 | u32 i = 0; |
752 | int ret = -1; | 721 | int ret = -1; |
753 | 722 | ||
754 | sprintf(filename, CORE_SIB_FMT, cpu); | 723 | sprintf(filename, CORE_SIB_FMT, cpu); |
755 | fp = fopen(filename, "r"); | 724 | fp = fopen(filename, "r"); |
756 | if (!fp) | 725 | if (!fp) |
757 | return -1; | 726 | goto try_threads; |
758 | |||
759 | if (getline(&buf, &len, fp) <= 0) | ||
760 | goto done; | ||
761 | 727 | ||
728 | sret = getline(&buf, &len, fp); | ||
762 | fclose(fp); | 729 | fclose(fp); |
730 | if (sret <= 0) | ||
731 | goto try_threads; | ||
763 | 732 | ||
764 | p = strchr(buf, '\n'); | 733 | p = strchr(buf, '\n'); |
765 | if (p) | 734 | if (p) |
@@ -775,7 +744,9 @@ static int build_cpu_topo(struct cpu_topo *tp, int cpu) | |||
775 | buf = NULL; | 744 | buf = NULL; |
776 | len = 0; | 745 | len = 0; |
777 | } | 746 | } |
747 | ret = 0; | ||
778 | 748 | ||
749 | try_threads: | ||
779 | sprintf(filename, THRD_SIB_FMT, cpu); | 750 | sprintf(filename, THRD_SIB_FMT, cpu); |
780 | fp = fopen(filename, "r"); | 751 | fp = fopen(filename, "r"); |
781 | if (!fp) | 752 | if (!fp) |
@@ -2257,7 +2228,7 @@ static int perf_header__adds_write(struct perf_header *header, | |||
2257 | 2228 | ||
2258 | sec_size = sizeof(*feat_sec) * nr_sections; | 2229 | sec_size = sizeof(*feat_sec) * nr_sections; |
2259 | 2230 | ||
2260 | sec_start = header->data_offset + header->data_size; | 2231 | sec_start = header->feat_offset; |
2261 | lseek(fd, sec_start + sec_size, SEEK_SET); | 2232 | lseek(fd, sec_start + sec_size, SEEK_SET); |
2262 | 2233 | ||
2263 | for_each_set_bit(feat, header->adds_features, HEADER_FEAT_BITS) { | 2234 | for_each_set_bit(feat, header->adds_features, HEADER_FEAT_BITS) { |
@@ -2304,6 +2275,7 @@ int perf_session__write_header(struct perf_session *session, | |||
2304 | struct perf_file_attr f_attr; | 2275 | struct perf_file_attr f_attr; |
2305 | struct perf_header *header = &session->header; | 2276 | struct perf_header *header = &session->header; |
2306 | struct perf_evsel *evsel; | 2277 | struct perf_evsel *evsel; |
2278 | u64 attr_offset; | ||
2307 | int err; | 2279 | int err; |
2308 | 2280 | ||
2309 | lseek(fd, sizeof(f_header), SEEK_SET); | 2281 | lseek(fd, sizeof(f_header), SEEK_SET); |
@@ -2317,7 +2289,7 @@ int perf_session__write_header(struct perf_session *session, | |||
2317 | } | 2289 | } |
2318 | } | 2290 | } |
2319 | 2291 | ||
2320 | header->attr_offset = lseek(fd, 0, SEEK_CUR); | 2292 | attr_offset = lseek(fd, 0, SEEK_CUR); |
2321 | 2293 | ||
2322 | list_for_each_entry(evsel, &evlist->entries, node) { | 2294 | list_for_each_entry(evsel, &evlist->entries, node) { |
2323 | f_attr = (struct perf_file_attr){ | 2295 | f_attr = (struct perf_file_attr){ |
@@ -2334,17 +2306,8 @@ int perf_session__write_header(struct perf_session *session, | |||
2334 | } | 2306 | } |
2335 | } | 2307 | } |
2336 | 2308 | ||
2337 | header->event_offset = lseek(fd, 0, SEEK_CUR); | ||
2338 | header->event_size = trace_event_count * sizeof(struct perf_trace_event_type); | ||
2339 | if (trace_events) { | ||
2340 | err = do_write(fd, trace_events, header->event_size); | ||
2341 | if (err < 0) { | ||
2342 | pr_debug("failed to write perf header events\n"); | ||
2343 | return err; | ||
2344 | } | ||
2345 | } | ||
2346 | |||
2347 | header->data_offset = lseek(fd, 0, SEEK_CUR); | 2309 | header->data_offset = lseek(fd, 0, SEEK_CUR); |
2310 | header->feat_offset = header->data_offset + header->data_size; | ||
2348 | 2311 | ||
2349 | if (at_exit) { | 2312 | if (at_exit) { |
2350 | err = perf_header__adds_write(header, evlist, fd); | 2313 | err = perf_header__adds_write(header, evlist, fd); |
@@ -2357,17 +2320,14 @@ int perf_session__write_header(struct perf_session *session, | |||
2357 | .size = sizeof(f_header), | 2320 | .size = sizeof(f_header), |
2358 | .attr_size = sizeof(f_attr), | 2321 | .attr_size = sizeof(f_attr), |
2359 | .attrs = { | 2322 | .attrs = { |
2360 | .offset = header->attr_offset, | 2323 | .offset = attr_offset, |
2361 | .size = evlist->nr_entries * sizeof(f_attr), | 2324 | .size = evlist->nr_entries * sizeof(f_attr), |
2362 | }, | 2325 | }, |
2363 | .data = { | 2326 | .data = { |
2364 | .offset = header->data_offset, | 2327 | .offset = header->data_offset, |
2365 | .size = header->data_size, | 2328 | .size = header->data_size, |
2366 | }, | 2329 | }, |
2367 | .event_types = { | 2330 | /* event_types is ignored, store zeros */ |
2368 | .offset = header->event_offset, | ||
2369 | .size = header->event_size, | ||
2370 | }, | ||
2371 | }; | 2331 | }; |
2372 | 2332 | ||
2373 | memcpy(&f_header.adds_features, &header->adds_features, sizeof(header->adds_features)); | 2333 | memcpy(&f_header.adds_features, &header->adds_features, sizeof(header->adds_features)); |
@@ -2417,7 +2377,7 @@ int perf_header__process_sections(struct perf_header *header, int fd, | |||
2417 | 2377 | ||
2418 | sec_size = sizeof(*feat_sec) * nr_sections; | 2378 | sec_size = sizeof(*feat_sec) * nr_sections; |
2419 | 2379 | ||
2420 | lseek(fd, header->data_offset + header->data_size, SEEK_SET); | 2380 | lseek(fd, header->feat_offset, SEEK_SET); |
2421 | 2381 | ||
2422 | err = perf_header__getbuffer64(header, fd, feat_sec, sec_size); | 2382 | err = perf_header__getbuffer64(header, fd, feat_sec, sec_size); |
2423 | if (err < 0) | 2383 | if (err < 0) |
@@ -2523,6 +2483,7 @@ static int check_magic_endian(u64 magic, uint64_t hdr_sz, | |||
2523 | /* check for legacy format */ | 2483 | /* check for legacy format */ |
2524 | ret = memcmp(&magic, __perf_magic1, sizeof(magic)); | 2484 | ret = memcmp(&magic, __perf_magic1, sizeof(magic)); |
2525 | if (ret == 0) { | 2485 | if (ret == 0) { |
2486 | ph->version = PERF_HEADER_VERSION_1; | ||
2526 | pr_debug("legacy perf.data format\n"); | 2487 | pr_debug("legacy perf.data format\n"); |
2527 | if (is_pipe) | 2488 | if (is_pipe) |
2528 | return try_all_pipe_abis(hdr_sz, ph); | 2489 | return try_all_pipe_abis(hdr_sz, ph); |
@@ -2544,6 +2505,7 @@ static int check_magic_endian(u64 magic, uint64_t hdr_sz, | |||
2544 | return -1; | 2505 | return -1; |
2545 | 2506 | ||
2546 | ph->needs_swap = true; | 2507 | ph->needs_swap = true; |
2508 | ph->version = PERF_HEADER_VERSION_2; | ||
2547 | 2509 | ||
2548 | return 0; | 2510 | return 0; |
2549 | } | 2511 | } |
@@ -2614,10 +2576,9 @@ int perf_file_header__read(struct perf_file_header *header, | |||
2614 | memcpy(&ph->adds_features, &header->adds_features, | 2576 | memcpy(&ph->adds_features, &header->adds_features, |
2615 | sizeof(ph->adds_features)); | 2577 | sizeof(ph->adds_features)); |
2616 | 2578 | ||
2617 | ph->event_offset = header->event_types.offset; | ||
2618 | ph->event_size = header->event_types.size; | ||
2619 | ph->data_offset = header->data.offset; | 2579 | ph->data_offset = header->data.offset; |
2620 | ph->data_size = header->data.size; | 2580 | ph->data_size = header->data.size; |
2581 | ph->feat_offset = header->data.offset + header->data.size; | ||
2621 | return 0; | 2582 | return 0; |
2622 | } | 2583 | } |
2623 | 2584 | ||
@@ -2666,19 +2627,17 @@ static int perf_file_header__read_pipe(struct perf_pipe_file_header *header, | |||
2666 | return 0; | 2627 | return 0; |
2667 | } | 2628 | } |
2668 | 2629 | ||
2669 | static int perf_header__read_pipe(struct perf_session *session, int fd) | 2630 | static int perf_header__read_pipe(struct perf_session *session) |
2670 | { | 2631 | { |
2671 | struct perf_header *header = &session->header; | 2632 | struct perf_header *header = &session->header; |
2672 | struct perf_pipe_file_header f_header; | 2633 | struct perf_pipe_file_header f_header; |
2673 | 2634 | ||
2674 | if (perf_file_header__read_pipe(&f_header, header, fd, | 2635 | if (perf_file_header__read_pipe(&f_header, header, session->fd, |
2675 | session->repipe) < 0) { | 2636 | session->repipe) < 0) { |
2676 | pr_debug("incompatible file format\n"); | 2637 | pr_debug("incompatible file format\n"); |
2677 | return -EINVAL; | 2638 | return -EINVAL; |
2678 | } | 2639 | } |
2679 | 2640 | ||
2680 | session->fd = fd; | ||
2681 | |||
2682 | return 0; | 2641 | return 0; |
2683 | } | 2642 | } |
2684 | 2643 | ||
@@ -2772,20 +2731,21 @@ static int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist, | |||
2772 | return 0; | 2731 | return 0; |
2773 | } | 2732 | } |
2774 | 2733 | ||
2775 | int perf_session__read_header(struct perf_session *session, int fd) | 2734 | int perf_session__read_header(struct perf_session *session) |
2776 | { | 2735 | { |
2777 | struct perf_header *header = &session->header; | 2736 | struct perf_header *header = &session->header; |
2778 | struct perf_file_header f_header; | 2737 | struct perf_file_header f_header; |
2779 | struct perf_file_attr f_attr; | 2738 | struct perf_file_attr f_attr; |
2780 | u64 f_id; | 2739 | u64 f_id; |
2781 | int nr_attrs, nr_ids, i, j; | 2740 | int nr_attrs, nr_ids, i, j; |
2741 | int fd = session->fd; | ||
2782 | 2742 | ||
2783 | session->evlist = perf_evlist__new(); | 2743 | session->evlist = perf_evlist__new(); |
2784 | if (session->evlist == NULL) | 2744 | if (session->evlist == NULL) |
2785 | return -ENOMEM; | 2745 | return -ENOMEM; |
2786 | 2746 | ||
2787 | if (session->fd_pipe) | 2747 | if (session->fd_pipe) |
2788 | return perf_header__read_pipe(session, fd); | 2748 | return perf_header__read_pipe(session); |
2789 | 2749 | ||
2790 | if (perf_file_header__read(&f_header, header, fd) < 0) | 2750 | if (perf_file_header__read(&f_header, header, fd) < 0) |
2791 | return -EINVAL; | 2751 | return -EINVAL; |
@@ -2839,22 +2799,9 @@ int perf_session__read_header(struct perf_session *session, int fd) | |||
2839 | 2799 | ||
2840 | symbol_conf.nr_events = nr_attrs; | 2800 | symbol_conf.nr_events = nr_attrs; |
2841 | 2801 | ||
2842 | if (f_header.event_types.size) { | ||
2843 | lseek(fd, f_header.event_types.offset, SEEK_SET); | ||
2844 | trace_events = malloc(f_header.event_types.size); | ||
2845 | if (trace_events == NULL) | ||
2846 | return -ENOMEM; | ||
2847 | if (perf_header__getbuffer64(header, fd, trace_events, | ||
2848 | f_header.event_types.size)) | ||
2849 | goto out_errno; | ||
2850 | trace_event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type); | ||
2851 | } | ||
2852 | |||
2853 | perf_header__process_sections(header, fd, &session->pevent, | 2802 | perf_header__process_sections(header, fd, &session->pevent, |
2854 | perf_file_section__process); | 2803 | perf_file_section__process); |
2855 | 2804 | ||
2856 | lseek(fd, header->data_offset, SEEK_SET); | ||
2857 | |||
2858 | if (perf_evlist__prepare_tracepoint_events(session->evlist, | 2805 | if (perf_evlist__prepare_tracepoint_events(session->evlist, |
2859 | session->pevent)) | 2806 | session->pevent)) |
2860 | goto out_delete_evlist; | 2807 | goto out_delete_evlist; |
@@ -2922,7 +2869,8 @@ int perf_event__synthesize_attrs(struct perf_tool *tool, | |||
2922 | return err; | 2869 | return err; |
2923 | } | 2870 | } |
2924 | 2871 | ||
2925 | int perf_event__process_attr(union perf_event *event, | 2872 | int perf_event__process_attr(struct perf_tool *tool __maybe_unused, |
2873 | union perf_event *event, | ||
2926 | struct perf_evlist **pevlist) | 2874 | struct perf_evlist **pevlist) |
2927 | { | 2875 | { |
2928 | u32 i, ids, n_ids; | 2876 | u32 i, ids, n_ids; |
@@ -2961,64 +2909,6 @@ int perf_event__process_attr(union perf_event *event, | |||
2961 | return 0; | 2909 | return 0; |
2962 | } | 2910 | } |
2963 | 2911 | ||
2964 | int perf_event__synthesize_event_type(struct perf_tool *tool, | ||
2965 | u64 event_id, char *name, | ||
2966 | perf_event__handler_t process, | ||
2967 | struct machine *machine) | ||
2968 | { | ||
2969 | union perf_event ev; | ||
2970 | size_t size = 0; | ||
2971 | int err = 0; | ||
2972 | |||
2973 | memset(&ev, 0, sizeof(ev)); | ||
2974 | |||
2975 | ev.event_type.event_type.event_id = event_id; | ||
2976 | memset(ev.event_type.event_type.name, 0, MAX_EVENT_NAME); | ||
2977 | strncpy(ev.event_type.event_type.name, name, MAX_EVENT_NAME - 1); | ||
2978 | |||
2979 | ev.event_type.header.type = PERF_RECORD_HEADER_EVENT_TYPE; | ||
2980 | size = strlen(ev.event_type.event_type.name); | ||
2981 | size = PERF_ALIGN(size, sizeof(u64)); | ||
2982 | ev.event_type.header.size = sizeof(ev.event_type) - | ||
2983 | (sizeof(ev.event_type.event_type.name) - size); | ||
2984 | |||
2985 | err = process(tool, &ev, NULL, machine); | ||
2986 | |||
2987 | return err; | ||
2988 | } | ||
2989 | |||
2990 | int perf_event__synthesize_event_types(struct perf_tool *tool, | ||
2991 | perf_event__handler_t process, | ||
2992 | struct machine *machine) | ||
2993 | { | ||
2994 | struct perf_trace_event_type *type; | ||
2995 | int i, err = 0; | ||
2996 | |||
2997 | for (i = 0; i < trace_event_count; i++) { | ||
2998 | type = &trace_events[i]; | ||
2999 | |||
3000 | err = perf_event__synthesize_event_type(tool, type->event_id, | ||
3001 | type->name, process, | ||
3002 | machine); | ||
3003 | if (err) { | ||
3004 | pr_debug("failed to create perf header event type\n"); | ||
3005 | return err; | ||
3006 | } | ||
3007 | } | ||
3008 | |||
3009 | return err; | ||
3010 | } | ||
3011 | |||
3012 | int perf_event__process_event_type(struct perf_tool *tool __maybe_unused, | ||
3013 | union perf_event *event) | ||
3014 | { | ||
3015 | if (perf_header__push_event(event->event_type.event_type.event_id, | ||
3016 | event->event_type.event_type.name) < 0) | ||
3017 | return -ENOMEM; | ||
3018 | |||
3019 | return 0; | ||
3020 | } | ||
3021 | |||
3022 | int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd, | 2912 | int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd, |
3023 | struct perf_evlist *evlist, | 2913 | struct perf_evlist *evlist, |
3024 | perf_event__handler_t process) | 2914 | perf_event__handler_t process) |
@@ -3065,7 +2955,8 @@ int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd, | |||
3065 | return aligned_size; | 2955 | return aligned_size; |
3066 | } | 2956 | } |
3067 | 2957 | ||
3068 | int perf_event__process_tracing_data(union perf_event *event, | 2958 | int perf_event__process_tracing_data(struct perf_tool *tool __maybe_unused, |
2959 | union perf_event *event, | ||
3069 | struct perf_session *session) | 2960 | struct perf_session *session) |
3070 | { | 2961 | { |
3071 | ssize_t size_read, padding, size = event->tracing_data.size; | 2962 | ssize_t size_read, padding, size = event->tracing_data.size; |