aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/header.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/header.c')
-rw-r--r--tools/perf/util/header.c161
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
26static bool no_buildid_cache = false; 26static bool no_buildid_cache = false;
27 27
28static int trace_event_count;
29static struct perf_trace_event_type *trace_events;
30
31static u32 header_argc; 28static u32 header_argc;
32static const char **header_argv; 29static const char **header_argv;
33 30
34int 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
53char *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
749try_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
2669static int perf_header__read_pipe(struct perf_session *session, int fd) 2630static 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
2775int perf_session__read_header(struct perf_session *session, int fd) 2734int 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
2925int perf_event__process_attr(union perf_event *event, 2872int 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
2964int 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
2990int 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
3012int 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
3022int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd, 2912int 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
3068int perf_event__process_tracing_data(union perf_event *event, 2958int 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;