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.c205
1 files changed, 57 insertions, 148 deletions
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index a4dafbee2511..ce69901176d8 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
@@ -231,9 +199,11 @@ static int write_buildid(char *name, size_t name_len, u8 *build_id,
231 return write_padded(fd, name, name_len + 1, len); 199 return write_padded(fd, name, name_len + 1, len);
232} 200}
233 201
234static int __dsos__write_buildid_table(struct list_head *head, pid_t pid, 202static int __dsos__write_buildid_table(struct list_head *head,
235 u16 misc, int fd) 203 struct machine *machine,
204 pid_t pid, u16 misc, int fd)
236{ 205{
206 char nm[PATH_MAX];
237 struct dso *pos; 207 struct dso *pos;
238 208
239 dsos__for_each_with_build_id(pos, head) { 209 dsos__for_each_with_build_id(pos, head) {
@@ -247,6 +217,10 @@ static int __dsos__write_buildid_table(struct list_head *head, pid_t pid,
247 if (is_vdso_map(pos->short_name)) { 217 if (is_vdso_map(pos->short_name)) {
248 name = (char *) VDSO__MAP_NAME; 218 name = (char *) VDSO__MAP_NAME;
249 name_len = sizeof(VDSO__MAP_NAME) + 1; 219 name_len = sizeof(VDSO__MAP_NAME) + 1;
220 } else if (dso__is_kcore(pos)) {
221 machine__mmap_name(machine, nm, sizeof(nm));
222 name = nm;
223 name_len = strlen(nm) + 1;
250 } else { 224 } else {
251 name = pos->long_name; 225 name = pos->long_name;
252 name_len = pos->long_name_len + 1; 226 name_len = pos->long_name_len + 1;
@@ -272,10 +246,10 @@ static int machine__write_buildid_table(struct machine *machine, int fd)
272 umisc = PERF_RECORD_MISC_GUEST_USER; 246 umisc = PERF_RECORD_MISC_GUEST_USER;
273 } 247 }
274 248
275 err = __dsos__write_buildid_table(&machine->kernel_dsos, machine->pid, 249 err = __dsos__write_buildid_table(&machine->kernel_dsos, machine,
276 kmisc, fd); 250 machine->pid, kmisc, fd);
277 if (err == 0) 251 if (err == 0)
278 err = __dsos__write_buildid_table(&machine->user_dsos, 252 err = __dsos__write_buildid_table(&machine->user_dsos, machine,
279 machine->pid, umisc, fd); 253 machine->pid, umisc, fd);
280 return err; 254 return err;
281} 255}
@@ -407,23 +381,31 @@ out_free:
407 return err; 381 return err;
408} 382}
409 383
410static int dso__cache_build_id(struct dso *dso, const char *debugdir) 384static int dso__cache_build_id(struct dso *dso, struct machine *machine,
385 const char *debugdir)
411{ 386{
412 bool is_kallsyms = dso->kernel && dso->long_name[0] != '/'; 387 bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
413 bool is_vdso = is_vdso_map(dso->short_name); 388 bool is_vdso = is_vdso_map(dso->short_name);
389 char *name = dso->long_name;
390 char nm[PATH_MAX];
414 391
415 return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), 392 if (dso__is_kcore(dso)) {
416 dso->long_name, debugdir, 393 is_kallsyms = true;
417 is_kallsyms, is_vdso); 394 machine__mmap_name(machine, nm, sizeof(nm));
395 name = nm;
396 }
397 return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name,
398 debugdir, is_kallsyms, is_vdso);
418} 399}
419 400
420static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir) 401static int __dsos__cache_build_ids(struct list_head *head,
402 struct machine *machine, const char *debugdir)
421{ 403{
422 struct dso *pos; 404 struct dso *pos;
423 int err = 0; 405 int err = 0;
424 406
425 dsos__for_each_with_build_id(pos, head) 407 dsos__for_each_with_build_id(pos, head)
426 if (dso__cache_build_id(pos, debugdir)) 408 if (dso__cache_build_id(pos, machine, debugdir))
427 err = -1; 409 err = -1;
428 410
429 return err; 411 return err;
@@ -431,8 +413,9 @@ static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir)
431 413
432static int machine__cache_build_ids(struct machine *machine, const char *debugdir) 414static int machine__cache_build_ids(struct machine *machine, const char *debugdir)
433{ 415{
434 int ret = __dsos__cache_build_ids(&machine->kernel_dsos, debugdir); 416 int ret = __dsos__cache_build_ids(&machine->kernel_dsos, machine,
435 ret |= __dsos__cache_build_ids(&machine->user_dsos, debugdir); 417 debugdir);
418 ret |= __dsos__cache_build_ids(&machine->user_dsos, machine, debugdir);
436 return ret; 419 return ret;
437} 420}
438 421
@@ -748,18 +731,19 @@ static int build_cpu_topo(struct cpu_topo *tp, int cpu)
748 char filename[MAXPATHLEN]; 731 char filename[MAXPATHLEN];
749 char *buf = NULL, *p; 732 char *buf = NULL, *p;
750 size_t len = 0; 733 size_t len = 0;
734 ssize_t sret;
751 u32 i = 0; 735 u32 i = 0;
752 int ret = -1; 736 int ret = -1;
753 737
754 sprintf(filename, CORE_SIB_FMT, cpu); 738 sprintf(filename, CORE_SIB_FMT, cpu);
755 fp = fopen(filename, "r"); 739 fp = fopen(filename, "r");
756 if (!fp) 740 if (!fp)
757 return -1; 741 goto try_threads;
758
759 if (getline(&buf, &len, fp) <= 0)
760 goto done;
761 742
743 sret = getline(&buf, &len, fp);
762 fclose(fp); 744 fclose(fp);
745 if (sret <= 0)
746 goto try_threads;
763 747
764 p = strchr(buf, '\n'); 748 p = strchr(buf, '\n');
765 if (p) 749 if (p)
@@ -775,7 +759,9 @@ static int build_cpu_topo(struct cpu_topo *tp, int cpu)
775 buf = NULL; 759 buf = NULL;
776 len = 0; 760 len = 0;
777 } 761 }
762 ret = 0;
778 763
764try_threads:
779 sprintf(filename, THRD_SIB_FMT, cpu); 765 sprintf(filename, THRD_SIB_FMT, cpu);
780 fp = fopen(filename, "r"); 766 fp = fopen(filename, "r");
781 if (!fp) 767 if (!fp)
@@ -1380,6 +1366,9 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
1380 1366
1381 fprintf(fp, ", precise_ip = %d", evsel->attr.precise_ip); 1367 fprintf(fp, ", precise_ip = %d", evsel->attr.precise_ip);
1382 1368
1369 fprintf(fp, ", attr_mmap2 = %d", evsel->attr.mmap2);
1370 fprintf(fp, ", attr_mmap = %d", evsel->attr.mmap);
1371 fprintf(fp, ", attr_mmap_data = %d", evsel->attr.mmap_data);
1383 if (evsel->ids) { 1372 if (evsel->ids) {
1384 fprintf(fp, ", id = {"); 1373 fprintf(fp, ", id = {");
1385 for (j = 0, id = evsel->id; j < evsel->ids; j++, id++) { 1374 for (j = 0, id = evsel->id; j < evsel->ids; j++, id++) {
@@ -2257,7 +2246,7 @@ static int perf_header__adds_write(struct perf_header *header,
2257 2246
2258 sec_size = sizeof(*feat_sec) * nr_sections; 2247 sec_size = sizeof(*feat_sec) * nr_sections;
2259 2248
2260 sec_start = header->data_offset + header->data_size; 2249 sec_start = header->feat_offset;
2261 lseek(fd, sec_start + sec_size, SEEK_SET); 2250 lseek(fd, sec_start + sec_size, SEEK_SET);
2262 2251
2263 for_each_set_bit(feat, header->adds_features, HEADER_FEAT_BITS) { 2252 for_each_set_bit(feat, header->adds_features, HEADER_FEAT_BITS) {
@@ -2304,6 +2293,7 @@ int perf_session__write_header(struct perf_session *session,
2304 struct perf_file_attr f_attr; 2293 struct perf_file_attr f_attr;
2305 struct perf_header *header = &session->header; 2294 struct perf_header *header = &session->header;
2306 struct perf_evsel *evsel; 2295 struct perf_evsel *evsel;
2296 u64 attr_offset;
2307 int err; 2297 int err;
2308 2298
2309 lseek(fd, sizeof(f_header), SEEK_SET); 2299 lseek(fd, sizeof(f_header), SEEK_SET);
@@ -2317,7 +2307,7 @@ int perf_session__write_header(struct perf_session *session,
2317 } 2307 }
2318 } 2308 }
2319 2309
2320 header->attr_offset = lseek(fd, 0, SEEK_CUR); 2310 attr_offset = lseek(fd, 0, SEEK_CUR);
2321 2311
2322 list_for_each_entry(evsel, &evlist->entries, node) { 2312 list_for_each_entry(evsel, &evlist->entries, node) {
2323 f_attr = (struct perf_file_attr){ 2313 f_attr = (struct perf_file_attr){
@@ -2334,17 +2324,8 @@ int perf_session__write_header(struct perf_session *session,
2334 } 2324 }
2335 } 2325 }
2336 2326
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); 2327 header->data_offset = lseek(fd, 0, SEEK_CUR);
2328 header->feat_offset = header->data_offset + header->data_size;
2348 2329
2349 if (at_exit) { 2330 if (at_exit) {
2350 err = perf_header__adds_write(header, evlist, fd); 2331 err = perf_header__adds_write(header, evlist, fd);
@@ -2357,17 +2338,14 @@ int perf_session__write_header(struct perf_session *session,
2357 .size = sizeof(f_header), 2338 .size = sizeof(f_header),
2358 .attr_size = sizeof(f_attr), 2339 .attr_size = sizeof(f_attr),
2359 .attrs = { 2340 .attrs = {
2360 .offset = header->attr_offset, 2341 .offset = attr_offset,
2361 .size = evlist->nr_entries * sizeof(f_attr), 2342 .size = evlist->nr_entries * sizeof(f_attr),
2362 }, 2343 },
2363 .data = { 2344 .data = {
2364 .offset = header->data_offset, 2345 .offset = header->data_offset,
2365 .size = header->data_size, 2346 .size = header->data_size,
2366 }, 2347 },
2367 .event_types = { 2348 /* event_types is ignored, store zeros */
2368 .offset = header->event_offset,
2369 .size = header->event_size,
2370 },
2371 }; 2349 };
2372 2350
2373 memcpy(&f_header.adds_features, &header->adds_features, sizeof(header->adds_features)); 2351 memcpy(&f_header.adds_features, &header->adds_features, sizeof(header->adds_features));
@@ -2417,7 +2395,7 @@ int perf_header__process_sections(struct perf_header *header, int fd,
2417 2395
2418 sec_size = sizeof(*feat_sec) * nr_sections; 2396 sec_size = sizeof(*feat_sec) * nr_sections;
2419 2397
2420 lseek(fd, header->data_offset + header->data_size, SEEK_SET); 2398 lseek(fd, header->feat_offset, SEEK_SET);
2421 2399
2422 err = perf_header__getbuffer64(header, fd, feat_sec, sec_size); 2400 err = perf_header__getbuffer64(header, fd, feat_sec, sec_size);
2423 if (err < 0) 2401 if (err < 0)
@@ -2523,6 +2501,7 @@ static int check_magic_endian(u64 magic, uint64_t hdr_sz,
2523 /* check for legacy format */ 2501 /* check for legacy format */
2524 ret = memcmp(&magic, __perf_magic1, sizeof(magic)); 2502 ret = memcmp(&magic, __perf_magic1, sizeof(magic));
2525 if (ret == 0) { 2503 if (ret == 0) {
2504 ph->version = PERF_HEADER_VERSION_1;
2526 pr_debug("legacy perf.data format\n"); 2505 pr_debug("legacy perf.data format\n");
2527 if (is_pipe) 2506 if (is_pipe)
2528 return try_all_pipe_abis(hdr_sz, ph); 2507 return try_all_pipe_abis(hdr_sz, ph);
@@ -2544,6 +2523,7 @@ static int check_magic_endian(u64 magic, uint64_t hdr_sz,
2544 return -1; 2523 return -1;
2545 2524
2546 ph->needs_swap = true; 2525 ph->needs_swap = true;
2526 ph->version = PERF_HEADER_VERSION_2;
2547 2527
2548 return 0; 2528 return 0;
2549} 2529}
@@ -2614,10 +2594,9 @@ int perf_file_header__read(struct perf_file_header *header,
2614 memcpy(&ph->adds_features, &header->adds_features, 2594 memcpy(&ph->adds_features, &header->adds_features,
2615 sizeof(ph->adds_features)); 2595 sizeof(ph->adds_features));
2616 2596
2617 ph->event_offset = header->event_types.offset;
2618 ph->event_size = header->event_types.size;
2619 ph->data_offset = header->data.offset; 2597 ph->data_offset = header->data.offset;
2620 ph->data_size = header->data.size; 2598 ph->data_size = header->data.size;
2599 ph->feat_offset = header->data.offset + header->data.size;
2621 return 0; 2600 return 0;
2622} 2601}
2623 2602
@@ -2666,19 +2645,17 @@ static int perf_file_header__read_pipe(struct perf_pipe_file_header *header,
2666 return 0; 2645 return 0;
2667} 2646}
2668 2647
2669static int perf_header__read_pipe(struct perf_session *session, int fd) 2648static int perf_header__read_pipe(struct perf_session *session)
2670{ 2649{
2671 struct perf_header *header = &session->header; 2650 struct perf_header *header = &session->header;
2672 struct perf_pipe_file_header f_header; 2651 struct perf_pipe_file_header f_header;
2673 2652
2674 if (perf_file_header__read_pipe(&f_header, header, fd, 2653 if (perf_file_header__read_pipe(&f_header, header, session->fd,
2675 session->repipe) < 0) { 2654 session->repipe) < 0) {
2676 pr_debug("incompatible file format\n"); 2655 pr_debug("incompatible file format\n");
2677 return -EINVAL; 2656 return -EINVAL;
2678 } 2657 }
2679 2658
2680 session->fd = fd;
2681
2682 return 0; 2659 return 0;
2683} 2660}
2684 2661
@@ -2772,20 +2749,21 @@ static int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist,
2772 return 0; 2749 return 0;
2773} 2750}
2774 2751
2775int perf_session__read_header(struct perf_session *session, int fd) 2752int perf_session__read_header(struct perf_session *session)
2776{ 2753{
2777 struct perf_header *header = &session->header; 2754 struct perf_header *header = &session->header;
2778 struct perf_file_header f_header; 2755 struct perf_file_header f_header;
2779 struct perf_file_attr f_attr; 2756 struct perf_file_attr f_attr;
2780 u64 f_id; 2757 u64 f_id;
2781 int nr_attrs, nr_ids, i, j; 2758 int nr_attrs, nr_ids, i, j;
2759 int fd = session->fd;
2782 2760
2783 session->evlist = perf_evlist__new(); 2761 session->evlist = perf_evlist__new();
2784 if (session->evlist == NULL) 2762 if (session->evlist == NULL)
2785 return -ENOMEM; 2763 return -ENOMEM;
2786 2764
2787 if (session->fd_pipe) 2765 if (session->fd_pipe)
2788 return perf_header__read_pipe(session, fd); 2766 return perf_header__read_pipe(session);
2789 2767
2790 if (perf_file_header__read(&f_header, header, fd) < 0) 2768 if (perf_file_header__read(&f_header, header, fd) < 0)
2791 return -EINVAL; 2769 return -EINVAL;
@@ -2839,22 +2817,9 @@ int perf_session__read_header(struct perf_session *session, int fd)
2839 2817
2840 symbol_conf.nr_events = nr_attrs; 2818 symbol_conf.nr_events = nr_attrs;
2841 2819
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, 2820 perf_header__process_sections(header, fd, &session->pevent,
2854 perf_file_section__process); 2821 perf_file_section__process);
2855 2822
2856 lseek(fd, header->data_offset, SEEK_SET);
2857
2858 if (perf_evlist__prepare_tracepoint_events(session->evlist, 2823 if (perf_evlist__prepare_tracepoint_events(session->evlist,
2859 session->pevent)) 2824 session->pevent))
2860 goto out_delete_evlist; 2825 goto out_delete_evlist;
@@ -2922,7 +2887,8 @@ int perf_event__synthesize_attrs(struct perf_tool *tool,
2922 return err; 2887 return err;
2923} 2888}
2924 2889
2925int perf_event__process_attr(union perf_event *event, 2890int perf_event__process_attr(struct perf_tool *tool __maybe_unused,
2891 union perf_event *event,
2926 struct perf_evlist **pevlist) 2892 struct perf_evlist **pevlist)
2927{ 2893{
2928 u32 i, ids, n_ids; 2894 u32 i, ids, n_ids;
@@ -2961,64 +2927,6 @@ int perf_event__process_attr(union perf_event *event,
2961 return 0; 2927 return 0;
2962} 2928}
2963 2929
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, 2930int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd,
3023 struct perf_evlist *evlist, 2931 struct perf_evlist *evlist,
3024 perf_event__handler_t process) 2932 perf_event__handler_t process)
@@ -3065,7 +2973,8 @@ int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd,
3065 return aligned_size; 2973 return aligned_size;
3066} 2974}
3067 2975
3068int perf_event__process_tracing_data(union perf_event *event, 2976int perf_event__process_tracing_data(struct perf_tool *tool __maybe_unused,
2977 union perf_event *event,
3069 struct perf_session *session) 2978 struct perf_session *session)
3070{ 2979{
3071 ssize_t size_read, padding, size = event->tracing_data.size; 2980 ssize_t size_read, padding, size = event->tracing_data.size;