hc
2023-12-08 01573e231f18eb2d99162747186f59511f56b64d
kernel/tools/perf/util/header.c
....@@ -1,7 +1,6 @@
11 // SPDX-License-Identifier: GPL-2.0
22 #include <errno.h>
33 #include <inttypes.h>
4
-#include "util.h"
54 #include "string2.h"
65 #include <sys/param.h>
76 #include <sys/types.h>
....@@ -13,17 +12,22 @@
1312 #include <linux/list.h>
1413 #include <linux/kernel.h>
1514 #include <linux/bitops.h>
15
+#include <linux/string.h>
1616 #include <linux/stringify.h>
17
+#include <linux/zalloc.h>
1718 #include <sys/stat.h>
1819 #include <sys/utsname.h>
1920 #include <linux/time64.h>
2021 #include <dirent.h>
22
+#include <bpf/libbpf.h>
23
+#include <perf/cpumap.h>
2124
25
+#include "dso.h"
2226 #include "evlist.h"
2327 #include "evsel.h"
28
+#include "util/evsel_fprintf.h"
2429 #include "header.h"
2530 #include "memswap.h"
26
-#include "../perf.h"
2731 #include "trace-event.h"
2832 #include "session.h"
2933 #include "symbol.h"
....@@ -39,8 +43,13 @@
3943 #include "tool.h"
4044 #include "time-utils.h"
4145 #include "units.h"
46
+#include "util/util.h" // perf_exe()
47
+#include "cputopo.h"
48
+#include "bpf-event.h"
49
+#include "clockid.h"
4250
43
-#include "sane_ctype.h"
51
+#include <linux/ctype.h>
52
+#include <internal/lib.h>
4453
4554 /*
4655 * magic2 = "PERFILE2"
....@@ -62,15 +71,6 @@
6271 struct perf_file_attr {
6372 struct perf_event_attr attr;
6473 struct perf_file_section ids;
65
-};
66
-
67
-struct feat_fd {
68
- struct perf_header *ph;
69
- int fd;
70
- void *buf; /* Either buf != NULL or fd >= 0 */
71
- ssize_t offset;
72
- size_t size;
73
- struct perf_evsel *events;
7474 };
7575
7676 void perf_header__set_feat(struct perf_header *header, int feat)
....@@ -295,16 +295,16 @@
295295 }
296296
297297 static int write_tracing_data(struct feat_fd *ff,
298
- struct perf_evlist *evlist)
298
+ struct evlist *evlist)
299299 {
300300 if (WARN(ff->buf, "Error: calling %s in pipe-mode.\n", __func__))
301301 return -1;
302302
303
- return read_tracing_data(ff->fd, &evlist->entries);
303
+ return read_tracing_data(ff->fd, &evlist->core.entries);
304304 }
305305
306306 static int write_build_id(struct feat_fd *ff,
307
- struct perf_evlist *evlist __maybe_unused)
307
+ struct evlist *evlist __maybe_unused)
308308 {
309309 struct perf_session *session;
310310 int err;
....@@ -328,7 +328,7 @@
328328 }
329329
330330 static int write_hostname(struct feat_fd *ff,
331
- struct perf_evlist *evlist __maybe_unused)
331
+ struct evlist *evlist __maybe_unused)
332332 {
333333 struct utsname uts;
334334 int ret;
....@@ -341,7 +341,7 @@
341341 }
342342
343343 static int write_osrelease(struct feat_fd *ff,
344
- struct perf_evlist *evlist __maybe_unused)
344
+ struct evlist *evlist __maybe_unused)
345345 {
346346 struct utsname uts;
347347 int ret;
....@@ -354,7 +354,7 @@
354354 }
355355
356356 static int write_arch(struct feat_fd *ff,
357
- struct perf_evlist *evlist __maybe_unused)
357
+ struct evlist *evlist __maybe_unused)
358358 {
359359 struct utsname uts;
360360 int ret;
....@@ -367,7 +367,7 @@
367367 }
368368
369369 static int write_version(struct feat_fd *ff,
370
- struct perf_evlist *evlist __maybe_unused)
370
+ struct evlist *evlist __maybe_unused)
371371 {
372372 return do_write_string(ff, perf_version_string);
373373 }
....@@ -413,10 +413,8 @@
413413 while (*p) {
414414 if (isspace(*p)) {
415415 char *r = p + 1;
416
- char *q = r;
416
+ char *q = skip_spaces(r);
417417 *p = ' ';
418
- while (*q && isspace(*q))
419
- q++;
420418 if (q != (p+1))
421419 while ((*r++ = *q++));
422420 }
....@@ -430,9 +428,27 @@
430428 }
431429
432430 static int write_cpudesc(struct feat_fd *ff,
433
- struct perf_evlist *evlist __maybe_unused)
431
+ struct evlist *evlist __maybe_unused)
434432 {
433
+#if defined(__powerpc__) || defined(__hppa__) || defined(__sparc__)
434
+#define CPUINFO_PROC { "cpu", }
435
+#elif defined(__s390__)
436
+#define CPUINFO_PROC { "vendor_id", }
437
+#elif defined(__sh__)
438
+#define CPUINFO_PROC { "cpu type", }
439
+#elif defined(__alpha__) || defined(__mips__)
440
+#define CPUINFO_PROC { "cpu model", }
441
+#elif defined(__arm__)
442
+#define CPUINFO_PROC { "model name", "Processor", }
443
+#elif defined(__arc__)
444
+#define CPUINFO_PROC { "Processor", }
445
+#elif defined(__xtensa__)
446
+#define CPUINFO_PROC { "core ID", }
447
+#else
448
+#define CPUINFO_PROC { "model name", }
449
+#endif
435450 const char *cpuinfo_procs[] = CPUINFO_PROC;
451
+#undef CPUINFO_PROC
436452 unsigned int i;
437453
438454 for (i = 0; i < ARRAY_SIZE(cpuinfo_procs); i++) {
....@@ -446,7 +462,7 @@
446462
447463
448464 static int write_nrcpus(struct feat_fd *ff,
449
- struct perf_evlist *evlist __maybe_unused)
465
+ struct evlist *evlist __maybe_unused)
450466 {
451467 long nr;
452468 u32 nrc, nra;
....@@ -468,13 +484,13 @@
468484 }
469485
470486 static int write_event_desc(struct feat_fd *ff,
471
- struct perf_evlist *evlist)
487
+ struct evlist *evlist)
472488 {
473
- struct perf_evsel *evsel;
489
+ struct evsel *evsel;
474490 u32 nre, nri, sz;
475491 int ret;
476492
477
- nre = evlist->nr_entries;
493
+ nre = evlist->core.nr_entries;
478494
479495 /*
480496 * write number of events
....@@ -486,13 +502,13 @@
486502 /*
487503 * size of perf_event_attr struct
488504 */
489
- sz = (u32)sizeof(evsel->attr);
505
+ sz = (u32)sizeof(evsel->core.attr);
490506 ret = do_write(ff, &sz, sizeof(sz));
491507 if (ret < 0)
492508 return ret;
493509
494510 evlist__for_each_entry(evlist, evsel) {
495
- ret = do_write(ff, &evsel->attr, sz);
511
+ ret = do_write(ff, &evsel->core.attr, sz);
496512 if (ret < 0)
497513 return ret;
498514 /*
....@@ -502,7 +518,7 @@
502518 * copy into an nri to be independent of the
503519 * type of ids,
504520 */
505
- nri = evsel->ids;
521
+ nri = evsel->core.ids;
506522 ret = do_write(ff, &nri, sizeof(nri));
507523 if (ret < 0)
508524 return ret;
....@@ -510,13 +526,13 @@
510526 /*
511527 * write event string as passed on cmdline
512528 */
513
- ret = do_write_string(ff, perf_evsel__name(evsel));
529
+ ret = do_write_string(ff, evsel__name(evsel));
514530 if (ret < 0)
515531 return ret;
516532 /*
517533 * write unique ids for this event
518534 */
519
- ret = do_write(ff, evsel->id, evsel->ids * sizeof(u64));
535
+ ret = do_write(ff, evsel->core.id, evsel->core.ids * sizeof(u64));
520536 if (ret < 0)
521537 return ret;
522538 }
....@@ -524,19 +540,13 @@
524540 }
525541
526542 static int write_cmdline(struct feat_fd *ff,
527
- struct perf_evlist *evlist __maybe_unused)
543
+ struct evlist *evlist __maybe_unused)
528544 {
529
- char buf[MAXPATHLEN];
530
- u32 n;
531
- int i, ret;
545
+ char pbuf[MAXPATHLEN], *buf;
546
+ int i, ret, n;
532547
533548 /* actual path to perf binary */
534
- ret = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
535
- if (ret <= 0)
536
- return -1;
537
-
538
- /* readlink() does not add null termination */
539
- buf[ret] = '\0';
549
+ buf = perf_exe(pbuf, MAXPATHLEN);
540550
541551 /* account for binary path */
542552 n = perf_env.nr_cmdline + 1;
....@@ -557,160 +567,15 @@
557567 return 0;
558568 }
559569
560
-#define CORE_SIB_FMT \
561
- "/sys/devices/system/cpu/cpu%d/topology/core_siblings_list"
562
-#define THRD_SIB_FMT \
563
- "/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list"
564
-
565
-struct cpu_topo {
566
- u32 cpu_nr;
567
- u32 core_sib;
568
- u32 thread_sib;
569
- char **core_siblings;
570
- char **thread_siblings;
571
-};
572
-
573
-static int build_cpu_topo(struct cpu_topo *tp, int cpu)
574
-{
575
- FILE *fp;
576
- char filename[MAXPATHLEN];
577
- char *buf = NULL, *p;
578
- size_t len = 0;
579
- ssize_t sret;
580
- u32 i = 0;
581
- int ret = -1;
582
-
583
- sprintf(filename, CORE_SIB_FMT, cpu);
584
- fp = fopen(filename, "r");
585
- if (!fp)
586
- goto try_threads;
587
-
588
- sret = getline(&buf, &len, fp);
589
- fclose(fp);
590
- if (sret <= 0)
591
- goto try_threads;
592
-
593
- p = strchr(buf, '\n');
594
- if (p)
595
- *p = '\0';
596
-
597
- for (i = 0; i < tp->core_sib; i++) {
598
- if (!strcmp(buf, tp->core_siblings[i]))
599
- break;
600
- }
601
- if (i == tp->core_sib) {
602
- tp->core_siblings[i] = buf;
603
- tp->core_sib++;
604
- buf = NULL;
605
- len = 0;
606
- }
607
- ret = 0;
608
-
609
-try_threads:
610
- sprintf(filename, THRD_SIB_FMT, cpu);
611
- fp = fopen(filename, "r");
612
- if (!fp)
613
- goto done;
614
-
615
- if (getline(&buf, &len, fp) <= 0)
616
- goto done;
617
-
618
- p = strchr(buf, '\n');
619
- if (p)
620
- *p = '\0';
621
-
622
- for (i = 0; i < tp->thread_sib; i++) {
623
- if (!strcmp(buf, tp->thread_siblings[i]))
624
- break;
625
- }
626
- if (i == tp->thread_sib) {
627
- tp->thread_siblings[i] = buf;
628
- tp->thread_sib++;
629
- buf = NULL;
630
- }
631
- ret = 0;
632
-done:
633
- if(fp)
634
- fclose(fp);
635
- free(buf);
636
- return ret;
637
-}
638
-
639
-static void free_cpu_topo(struct cpu_topo *tp)
640
-{
641
- u32 i;
642
-
643
- if (!tp)
644
- return;
645
-
646
- for (i = 0 ; i < tp->core_sib; i++)
647
- zfree(&tp->core_siblings[i]);
648
-
649
- for (i = 0 ; i < tp->thread_sib; i++)
650
- zfree(&tp->thread_siblings[i]);
651
-
652
- free(tp);
653
-}
654
-
655
-static struct cpu_topo *build_cpu_topology(void)
656
-{
657
- struct cpu_topo *tp = NULL;
658
- void *addr;
659
- u32 nr, i;
660
- size_t sz;
661
- long ncpus;
662
- int ret = -1;
663
- struct cpu_map *map;
664
-
665
- ncpus = cpu__max_present_cpu();
666
-
667
- /* build online CPU map */
668
- map = cpu_map__new(NULL);
669
- if (map == NULL) {
670
- pr_debug("failed to get system cpumap\n");
671
- return NULL;
672
- }
673
-
674
- nr = (u32)(ncpus & UINT_MAX);
675
-
676
- sz = nr * sizeof(char *);
677
- addr = calloc(1, sizeof(*tp) + 2 * sz);
678
- if (!addr)
679
- goto out_free;
680
-
681
- tp = addr;
682
- tp->cpu_nr = nr;
683
- addr += sizeof(*tp);
684
- tp->core_siblings = addr;
685
- addr += sz;
686
- tp->thread_siblings = addr;
687
-
688
- for (i = 0; i < nr; i++) {
689
- if (!cpu_map__has(map, i))
690
- continue;
691
-
692
- ret = build_cpu_topo(tp, i);
693
- if (ret < 0)
694
- break;
695
- }
696
-
697
-out_free:
698
- cpu_map__put(map);
699
- if (ret) {
700
- free_cpu_topo(tp);
701
- tp = NULL;
702
- }
703
- return tp;
704
-}
705570
706571 static int write_cpu_topology(struct feat_fd *ff,
707
- struct perf_evlist *evlist __maybe_unused)
572
+ struct evlist *evlist __maybe_unused)
708573 {
709
- struct cpu_topo *tp;
574
+ struct cpu_topology *tp;
710575 u32 i;
711576 int ret, j;
712577
713
- tp = build_cpu_topology();
578
+ tp = cpu_topology__new();
714579 if (!tp)
715580 return -1;
716581
....@@ -747,15 +612,36 @@
747612 if (ret < 0)
748613 return ret;
749614 }
615
+
616
+ if (!tp->die_sib)
617
+ goto done;
618
+
619
+ ret = do_write(ff, &tp->die_sib, sizeof(tp->die_sib));
620
+ if (ret < 0)
621
+ goto done;
622
+
623
+ for (i = 0; i < tp->die_sib; i++) {
624
+ ret = do_write_string(ff, tp->die_siblings[i]);
625
+ if (ret < 0)
626
+ goto done;
627
+ }
628
+
629
+ for (j = 0; j < perf_env.nr_cpus_avail; j++) {
630
+ ret = do_write(ff, &perf_env.cpu[j].die_id,
631
+ sizeof(perf_env.cpu[j].die_id));
632
+ if (ret < 0)
633
+ return ret;
634
+ }
635
+
750636 done:
751
- free_cpu_topo(tp);
637
+ cpu_topology__delete(tp);
752638 return ret;
753639 }
754640
755641
756642
757643 static int write_total_mem(struct feat_fd *ff,
758
- struct perf_evlist *evlist __maybe_unused)
644
+ struct evlist *evlist __maybe_unused)
759645 {
760646 char *buf = NULL;
761647 FILE *fp;
....@@ -783,112 +669,45 @@
783669 return ret;
784670 }
785671
786
-static int write_topo_node(struct feat_fd *ff, int node)
787
-{
788
- char str[MAXPATHLEN];
789
- char field[32];
790
- char *buf = NULL, *p;
791
- size_t len = 0;
792
- FILE *fp;
793
- u64 mem_total, mem_free, mem;
794
- int ret = -1;
795
-
796
- sprintf(str, "/sys/devices/system/node/node%d/meminfo", node);
797
- fp = fopen(str, "r");
798
- if (!fp)
799
- return -1;
800
-
801
- while (getline(&buf, &len, fp) > 0) {
802
- /* skip over invalid lines */
803
- if (!strchr(buf, ':'))
804
- continue;
805
- if (sscanf(buf, "%*s %*d %31s %"PRIu64, field, &mem) != 2)
806
- goto done;
807
- if (!strcmp(field, "MemTotal:"))
808
- mem_total = mem;
809
- if (!strcmp(field, "MemFree:"))
810
- mem_free = mem;
811
- }
812
-
813
- fclose(fp);
814
- fp = NULL;
815
-
816
- ret = do_write(ff, &mem_total, sizeof(u64));
817
- if (ret)
818
- goto done;
819
-
820
- ret = do_write(ff, &mem_free, sizeof(u64));
821
- if (ret)
822
- goto done;
823
-
824
- ret = -1;
825
- sprintf(str, "/sys/devices/system/node/node%d/cpulist", node);
826
-
827
- fp = fopen(str, "r");
828
- if (!fp)
829
- goto done;
830
-
831
- if (getline(&buf, &len, fp) <= 0)
832
- goto done;
833
-
834
- p = strchr(buf, '\n');
835
- if (p)
836
- *p = '\0';
837
-
838
- ret = do_write_string(ff, buf);
839
-done:
840
- free(buf);
841
- if (fp)
842
- fclose(fp);
843
- return ret;
844
-}
845
-
846672 static int write_numa_topology(struct feat_fd *ff,
847
- struct perf_evlist *evlist __maybe_unused)
673
+ struct evlist *evlist __maybe_unused)
848674 {
849
- char *buf = NULL;
850
- size_t len = 0;
851
- FILE *fp;
852
- struct cpu_map *node_map = NULL;
853
- char *c;
854
- u32 nr, i, j;
675
+ struct numa_topology *tp;
855676 int ret = -1;
677
+ u32 i;
856678
857
- fp = fopen("/sys/devices/system/node/online", "r");
858
- if (!fp)
859
- return -1;
679
+ tp = numa_topology__new();
680
+ if (!tp)
681
+ return -ENOMEM;
860682
861
- if (getline(&buf, &len, fp) <= 0)
862
- goto done;
863
-
864
- c = strchr(buf, '\n');
865
- if (c)
866
- *c = '\0';
867
-
868
- node_map = cpu_map__new(buf);
869
- if (!node_map)
870
- goto done;
871
-
872
- nr = (u32)node_map->nr;
873
-
874
- ret = do_write(ff, &nr, sizeof(nr));
683
+ ret = do_write(ff, &tp->nr, sizeof(u32));
875684 if (ret < 0)
876
- goto done;
685
+ goto err;
877686
878
- for (i = 0; i < nr; i++) {
879
- j = (u32)node_map->map[i];
880
- ret = do_write(ff, &j, sizeof(j));
881
- if (ret < 0)
882
- break;
687
+ for (i = 0; i < tp->nr; i++) {
688
+ struct numa_topology_node *n = &tp->nodes[i];
883689
884
- ret = write_topo_node(ff, i);
690
+ ret = do_write(ff, &n->node, sizeof(u32));
885691 if (ret < 0)
886
- break;
692
+ goto err;
693
+
694
+ ret = do_write(ff, &n->mem_total, sizeof(u64));
695
+ if (ret)
696
+ goto err;
697
+
698
+ ret = do_write(ff, &n->mem_free, sizeof(u64));
699
+ if (ret)
700
+ goto err;
701
+
702
+ ret = do_write_string(ff, n->cpus);
703
+ if (ret < 0)
704
+ goto err;
887705 }
888
-done:
889
- free(buf);
890
- fclose(fp);
891
- cpu_map__put(node_map);
706
+
707
+ ret = 0;
708
+
709
+err:
710
+ numa_topology__delete(tp);
892711 return ret;
893712 }
894713
....@@ -905,7 +724,7 @@
905724 */
906725
907726 static int write_pmu_mappings(struct feat_fd *ff,
908
- struct perf_evlist *evlist __maybe_unused)
727
+ struct evlist *evlist __maybe_unused)
909728 {
910729 struct perf_pmu *pmu = NULL;
911730 u32 pmu_num = 0;
....@@ -954,10 +773,10 @@
954773 * };
955774 */
956775 static int write_group_desc(struct feat_fd *ff,
957
- struct perf_evlist *evlist)
776
+ struct evlist *evlist)
958777 {
959778 u32 nr_groups = evlist->nr_groups;
960
- struct perf_evsel *evsel;
779
+ struct evsel *evsel;
961780 int ret;
962781
963782 ret = do_write(ff, &nr_groups, sizeof(nr_groups));
....@@ -965,11 +784,10 @@
965784 return ret;
966785
967786 evlist__for_each_entry(evlist, evsel) {
968
- if (perf_evsel__is_group_leader(evsel) &&
969
- evsel->nr_members > 1) {
787
+ if (evsel__is_group_leader(evsel) && evsel->core.nr_members > 1) {
970788 const char *name = evsel->group_name ?: "{anon_group}";
971789 u32 leader_idx = evsel->idx;
972
- u32 nr_members = evsel->nr_members;
790
+ u32 nr_members = evsel->core.nr_members;
973791
974792 ret = do_write_string(ff, name);
975793 if (ret < 0)
....@@ -988,37 +806,74 @@
988806 }
989807
990808 /*
809
+ * Return the CPU id as a raw string.
810
+ *
811
+ * Each architecture should provide a more precise id string that
812
+ * can be use to match the architecture's "mapfile".
813
+ */
814
+char * __weak get_cpuid_str(struct perf_pmu *pmu __maybe_unused)
815
+{
816
+ return NULL;
817
+}
818
+
819
+/* Return zero when the cpuid from the mapfile.csv matches the
820
+ * cpuid string generated on this platform.
821
+ * Otherwise return non-zero.
822
+ */
823
+int __weak strcmp_cpuid_str(const char *mapcpuid, const char *cpuid)
824
+{
825
+ regex_t re;
826
+ regmatch_t pmatch[1];
827
+ int match;
828
+
829
+ if (regcomp(&re, mapcpuid, REG_EXTENDED) != 0) {
830
+ /* Warn unable to generate match particular string. */
831
+ pr_info("Invalid regular expression %s\n", mapcpuid);
832
+ return 1;
833
+ }
834
+
835
+ match = !regexec(&re, cpuid, 1, pmatch, 0);
836
+ regfree(&re);
837
+ if (match) {
838
+ size_t match_len = (pmatch[0].rm_eo - pmatch[0].rm_so);
839
+
840
+ /* Verify the entire string matched. */
841
+ if (match_len == strlen(cpuid))
842
+ return 0;
843
+ }
844
+ return 1;
845
+}
846
+
847
+/*
991848 * default get_cpuid(): nothing gets recorded
992849 * actual implementation must be in arch/$(SRCARCH)/util/header.c
993850 */
994851 int __weak get_cpuid(char *buffer __maybe_unused, size_t sz __maybe_unused)
995852 {
996
- return -1;
853
+ return ENOSYS; /* Not implemented */
997854 }
998855
999856 static int write_cpuid(struct feat_fd *ff,
1000
- struct perf_evlist *evlist __maybe_unused)
857
+ struct evlist *evlist __maybe_unused)
1001858 {
1002859 char buffer[64];
1003860 int ret;
1004861
1005862 ret = get_cpuid(buffer, sizeof(buffer));
1006
- if (!ret)
1007
- goto write_it;
863
+ if (ret)
864
+ return -1;
1008865
1009
- return -1;
1010
-write_it:
1011866 return do_write_string(ff, buffer);
1012867 }
1013868
1014869 static int write_branch_stack(struct feat_fd *ff __maybe_unused,
1015
- struct perf_evlist *evlist __maybe_unused)
870
+ struct evlist *evlist __maybe_unused)
1016871 {
1017872 return 0;
1018873 }
1019874
1020875 static int write_auxtrace(struct feat_fd *ff,
1021
- struct perf_evlist *evlist __maybe_unused)
876
+ struct evlist *evlist __maybe_unused)
1022877 {
1023878 struct perf_session *session;
1024879 int err;
....@@ -1032,6 +887,145 @@
1032887 if (err < 0)
1033888 pr_err("Failed to write auxtrace index\n");
1034889 return err;
890
+}
891
+
892
+static int write_clockid(struct feat_fd *ff,
893
+ struct evlist *evlist __maybe_unused)
894
+{
895
+ return do_write(ff, &ff->ph->env.clock.clockid_res_ns,
896
+ sizeof(ff->ph->env.clock.clockid_res_ns));
897
+}
898
+
899
+static int write_clock_data(struct feat_fd *ff,
900
+ struct evlist *evlist __maybe_unused)
901
+{
902
+ u64 *data64;
903
+ u32 data32;
904
+ int ret;
905
+
906
+ /* version */
907
+ data32 = 1;
908
+
909
+ ret = do_write(ff, &data32, sizeof(data32));
910
+ if (ret < 0)
911
+ return ret;
912
+
913
+ /* clockid */
914
+ data32 = ff->ph->env.clock.clockid;
915
+
916
+ ret = do_write(ff, &data32, sizeof(data32));
917
+ if (ret < 0)
918
+ return ret;
919
+
920
+ /* TOD ref time */
921
+ data64 = &ff->ph->env.clock.tod_ns;
922
+
923
+ ret = do_write(ff, data64, sizeof(*data64));
924
+ if (ret < 0)
925
+ return ret;
926
+
927
+ /* clockid ref time */
928
+ data64 = &ff->ph->env.clock.clockid_ns;
929
+
930
+ return do_write(ff, data64, sizeof(*data64));
931
+}
932
+
933
+static int write_dir_format(struct feat_fd *ff,
934
+ struct evlist *evlist __maybe_unused)
935
+{
936
+ struct perf_session *session;
937
+ struct perf_data *data;
938
+
939
+ session = container_of(ff->ph, struct perf_session, header);
940
+ data = session->data;
941
+
942
+ if (WARN_ON(!perf_data__is_dir(data)))
943
+ return -1;
944
+
945
+ return do_write(ff, &data->dir.version, sizeof(data->dir.version));
946
+}
947
+
948
+#ifdef HAVE_LIBBPF_SUPPORT
949
+static int write_bpf_prog_info(struct feat_fd *ff,
950
+ struct evlist *evlist __maybe_unused)
951
+{
952
+ struct perf_env *env = &ff->ph->env;
953
+ struct rb_root *root;
954
+ struct rb_node *next;
955
+ int ret;
956
+
957
+ down_read(&env->bpf_progs.lock);
958
+
959
+ ret = do_write(ff, &env->bpf_progs.infos_cnt,
960
+ sizeof(env->bpf_progs.infos_cnt));
961
+ if (ret < 0)
962
+ goto out;
963
+
964
+ root = &env->bpf_progs.infos;
965
+ next = rb_first(root);
966
+ while (next) {
967
+ struct bpf_prog_info_node *node;
968
+ size_t len;
969
+
970
+ node = rb_entry(next, struct bpf_prog_info_node, rb_node);
971
+ next = rb_next(&node->rb_node);
972
+ len = sizeof(struct bpf_prog_info_linear) +
973
+ node->info_linear->data_len;
974
+
975
+ /* before writing to file, translate address to offset */
976
+ bpf_program__bpil_addr_to_offs(node->info_linear);
977
+ ret = do_write(ff, node->info_linear, len);
978
+ /*
979
+ * translate back to address even when do_write() fails,
980
+ * so that this function never changes the data.
981
+ */
982
+ bpf_program__bpil_offs_to_addr(node->info_linear);
983
+ if (ret < 0)
984
+ goto out;
985
+ }
986
+out:
987
+ up_read(&env->bpf_progs.lock);
988
+ return ret;
989
+}
990
+#else // HAVE_LIBBPF_SUPPORT
991
+static int write_bpf_prog_info(struct feat_fd *ff __maybe_unused,
992
+ struct evlist *evlist __maybe_unused)
993
+{
994
+ return 0;
995
+}
996
+#endif // HAVE_LIBBPF_SUPPORT
997
+
998
+static int write_bpf_btf(struct feat_fd *ff,
999
+ struct evlist *evlist __maybe_unused)
1000
+{
1001
+ struct perf_env *env = &ff->ph->env;
1002
+ struct rb_root *root;
1003
+ struct rb_node *next;
1004
+ int ret;
1005
+
1006
+ down_read(&env->bpf_progs.lock);
1007
+
1008
+ ret = do_write(ff, &env->bpf_progs.btfs_cnt,
1009
+ sizeof(env->bpf_progs.btfs_cnt));
1010
+
1011
+ if (ret < 0)
1012
+ goto out;
1013
+
1014
+ root = &env->bpf_progs.btfs;
1015
+ next = rb_first(root);
1016
+ while (next) {
1017
+ struct btf_node *node;
1018
+
1019
+ node = rb_entry(next, struct btf_node, rb_node);
1020
+ next = rb_next(&node->rb_node);
1021
+ ret = do_write(ff, &node->id,
1022
+ sizeof(u32) * 2 + node->data_size);
1023
+ if (ret < 0)
1024
+ goto out;
1025
+ }
1026
+out:
1027
+ up_read(&env->bpf_progs.lock);
1028
+ return ret;
10351029 }
10361030
10371031 static int cpu_cache_level__sort(const void *a, const void *b)
....@@ -1101,26 +1095,26 @@
11011095 return -1;
11021096
11031097 cache->type[len] = 0;
1104
- cache->type = rtrim(cache->type);
1098
+ cache->type = strim(cache->type);
11051099
11061100 scnprintf(file, PATH_MAX, "%s/size", path);
11071101 if (sysfs__read_str(file, &cache->size, &len)) {
1108
- free(cache->type);
1102
+ zfree(&cache->type);
11091103 return -1;
11101104 }
11111105
11121106 cache->size[len] = 0;
1113
- cache->size = rtrim(cache->size);
1107
+ cache->size = strim(cache->size);
11141108
11151109 scnprintf(file, PATH_MAX, "%s/shared_cpu_list", path);
11161110 if (sysfs__read_str(file, &cache->map, &len)) {
1117
- free(cache->size);
1118
- free(cache->type);
1111
+ zfree(&cache->size);
1112
+ zfree(&cache->type);
11191113 return -1;
11201114 }
11211115
11221116 cache->map[len] = 0;
1123
- cache->map = rtrim(cache->map);
1117
+ cache->map = strim(cache->map);
11241118 return 0;
11251119 }
11261120
....@@ -1129,21 +1123,18 @@
11291123 fprintf(out, "L%d %-15s %8s [%s]\n", c->level, c->type, c->size, c->map);
11301124 }
11311125
1132
-static int build_caches(struct cpu_cache_level caches[], u32 size, u32 *cntp)
1126
+#define MAX_CACHE_LVL 4
1127
+
1128
+static int build_caches(struct cpu_cache_level caches[], u32 *cntp)
11331129 {
11341130 u32 i, cnt = 0;
1135
- long ncpus;
11361131 u32 nr, cpu;
11371132 u16 level;
11381133
1139
- ncpus = sysconf(_SC_NPROCESSORS_CONF);
1140
- if (ncpus < 0)
1141
- return -1;
1142
-
1143
- nr = (u32)(ncpus & UINT_MAX);
1134
+ nr = cpu__max_cpu();
11441135
11451136 for (cpu = 0; cpu < nr; cpu++) {
1146
- for (level = 0; level < 10; level++) {
1137
+ for (level = 0; level < MAX_CACHE_LVL; level++) {
11471138 struct cpu_cache_level c;
11481139 int err;
11491140
....@@ -1163,26 +1154,21 @@
11631154 caches[cnt++] = c;
11641155 else
11651156 cpu_cache_level__free(&c);
1166
-
1167
- if (WARN_ONCE(cnt == size, "way too many cpu caches.."))
1168
- goto out;
11691157 }
11701158 }
1171
- out:
11721159 *cntp = cnt;
11731160 return 0;
11741161 }
11751162
1176
-#define MAX_CACHES (MAX_NR_CPUS * 4)
1177
-
11781163 static int write_cache(struct feat_fd *ff,
1179
- struct perf_evlist *evlist __maybe_unused)
1164
+ struct evlist *evlist __maybe_unused)
11801165 {
1181
- struct cpu_cache_level caches[MAX_CACHES];
1166
+ u32 max_caches = cpu__max_cpu() * MAX_CACHE_LVL;
1167
+ struct cpu_cache_level caches[max_caches];
11821168 u32 cnt = 0, i, version = 1;
11831169 int ret;
11841170
1185
- ret = build_caches(caches, MAX_CACHES, &cnt);
1171
+ ret = build_caches(caches, &cnt);
11861172 if (ret)
11871173 goto out;
11881174
....@@ -1228,13 +1214,13 @@
12281214 }
12291215
12301216 static int write_stat(struct feat_fd *ff __maybe_unused,
1231
- struct perf_evlist *evlist __maybe_unused)
1217
+ struct evlist *evlist __maybe_unused)
12321218 {
12331219 return 0;
12341220 }
12351221
12361222 static int write_sample_time(struct feat_fd *ff,
1237
- struct perf_evlist *evlist)
1223
+ struct evlist *evlist)
12381224 {
12391225 int ret;
12401226
....@@ -1335,8 +1321,10 @@
13351321 continue;
13361322
13371323 if (WARN_ONCE(cnt >= size,
1338
- "failed to write MEM_TOPOLOGY, way too many nodes\n"))
1324
+ "failed to write MEM_TOPOLOGY, way too many nodes\n")) {
1325
+ closedir(dir);
13391326 return -1;
1327
+ }
13401328
13411329 ret = memory_node__read(&nodes[cnt++], idx);
13421330 }
....@@ -1368,7 +1356,7 @@
13681356 * 48 - bitmap | bitmap of memory indexes that belongs to node
13691357 */
13701358 static int write_mem_topology(struct feat_fd *ff __maybe_unused,
1371
- struct perf_evlist *evlist __maybe_unused)
1359
+ struct evlist *evlist __maybe_unused)
13721360 {
13731361 static struct memory_node nodes[MAX_MEMORY_NODES];
13741362 u64 bsize, version = 1, i, nr;
....@@ -1414,6 +1402,62 @@
14141402 }
14151403
14161404 out:
1405
+ return ret;
1406
+}
1407
+
1408
+static int write_compressed(struct feat_fd *ff __maybe_unused,
1409
+ struct evlist *evlist __maybe_unused)
1410
+{
1411
+ int ret;
1412
+
1413
+ ret = do_write(ff, &(ff->ph->env.comp_ver), sizeof(ff->ph->env.comp_ver));
1414
+ if (ret)
1415
+ return ret;
1416
+
1417
+ ret = do_write(ff, &(ff->ph->env.comp_type), sizeof(ff->ph->env.comp_type));
1418
+ if (ret)
1419
+ return ret;
1420
+
1421
+ ret = do_write(ff, &(ff->ph->env.comp_level), sizeof(ff->ph->env.comp_level));
1422
+ if (ret)
1423
+ return ret;
1424
+
1425
+ ret = do_write(ff, &(ff->ph->env.comp_ratio), sizeof(ff->ph->env.comp_ratio));
1426
+ if (ret)
1427
+ return ret;
1428
+
1429
+ return do_write(ff, &(ff->ph->env.comp_mmap_len), sizeof(ff->ph->env.comp_mmap_len));
1430
+}
1431
+
1432
+static int write_cpu_pmu_caps(struct feat_fd *ff,
1433
+ struct evlist *evlist __maybe_unused)
1434
+{
1435
+ struct perf_pmu *cpu_pmu = perf_pmu__find("cpu");
1436
+ struct perf_pmu_caps *caps = NULL;
1437
+ int nr_caps;
1438
+ int ret;
1439
+
1440
+ if (!cpu_pmu)
1441
+ return -ENOENT;
1442
+
1443
+ nr_caps = perf_pmu__caps_parse(cpu_pmu);
1444
+ if (nr_caps < 0)
1445
+ return nr_caps;
1446
+
1447
+ ret = do_write(ff, &nr_caps, sizeof(nr_caps));
1448
+ if (ret < 0)
1449
+ return ret;
1450
+
1451
+ list_for_each_entry(caps, &cpu_pmu->caps, list) {
1452
+ ret = do_write_string(ff, caps->name);
1453
+ if (ret < 0)
1454
+ return ret;
1455
+
1456
+ ret = do_write_string(ff, caps->value);
1457
+ if (ret < 0)
1458
+ return ret;
1459
+ }
1460
+
14171461 return ret;
14181462 }
14191463
....@@ -1488,8 +1532,18 @@
14881532 str = ph->env.sibling_cores;
14891533
14901534 for (i = 0; i < nr; i++) {
1491
- fprintf(fp, "# sibling cores : %s\n", str);
1535
+ fprintf(fp, "# sibling sockets : %s\n", str);
14921536 str += strlen(str) + 1;
1537
+ }
1538
+
1539
+ if (ph->env.nr_sibling_dies) {
1540
+ nr = ph->env.nr_sibling_dies;
1541
+ str = ph->env.sibling_dies;
1542
+
1543
+ for (i = 0; i < nr; i++) {
1544
+ fprintf(fp, "# sibling dies : %s\n", str);
1545
+ str += strlen(str) + 1;
1546
+ }
14931547 }
14941548
14951549 nr = ph->env.nr_sibling_threads;
....@@ -1500,32 +1554,188 @@
15001554 str += strlen(str) + 1;
15011555 }
15021556
1503
- if (ph->env.cpu != NULL) {
1504
- for (i = 0; i < cpu_nr; i++)
1505
- fprintf(fp, "# CPU %d: Core ID %d, Socket ID %d\n", i,
1506
- ph->env.cpu[i].core_id, ph->env.cpu[i].socket_id);
1507
- } else
1508
- fprintf(fp, "# Core ID and Socket ID information is not available\n");
1557
+ if (ph->env.nr_sibling_dies) {
1558
+ if (ph->env.cpu != NULL) {
1559
+ for (i = 0; i < cpu_nr; i++)
1560
+ fprintf(fp, "# CPU %d: Core ID %d, "
1561
+ "Die ID %d, Socket ID %d\n",
1562
+ i, ph->env.cpu[i].core_id,
1563
+ ph->env.cpu[i].die_id,
1564
+ ph->env.cpu[i].socket_id);
1565
+ } else
1566
+ fprintf(fp, "# Core ID, Die ID and Socket ID "
1567
+ "information is not available\n");
1568
+ } else {
1569
+ if (ph->env.cpu != NULL) {
1570
+ for (i = 0; i < cpu_nr; i++)
1571
+ fprintf(fp, "# CPU %d: Core ID %d, "
1572
+ "Socket ID %d\n",
1573
+ i, ph->env.cpu[i].core_id,
1574
+ ph->env.cpu[i].socket_id);
1575
+ } else
1576
+ fprintf(fp, "# Core ID and Socket ID "
1577
+ "information is not available\n");
1578
+ }
15091579 }
15101580
1511
-static void free_event_desc(struct perf_evsel *events)
1581
+static void print_clockid(struct feat_fd *ff, FILE *fp)
15121582 {
1513
- struct perf_evsel *evsel;
1583
+ fprintf(fp, "# clockid frequency: %"PRIu64" MHz\n",
1584
+ ff->ph->env.clock.clockid_res_ns * 1000);
1585
+}
1586
+
1587
+static void print_clock_data(struct feat_fd *ff, FILE *fp)
1588
+{
1589
+ struct timespec clockid_ns;
1590
+ char tstr[64], date[64];
1591
+ struct timeval tod_ns;
1592
+ clockid_t clockid;
1593
+ struct tm ltime;
1594
+ u64 ref;
1595
+
1596
+ if (!ff->ph->env.clock.enabled) {
1597
+ fprintf(fp, "# reference time disabled\n");
1598
+ return;
1599
+ }
1600
+
1601
+ /* Compute TOD time. */
1602
+ ref = ff->ph->env.clock.tod_ns;
1603
+ tod_ns.tv_sec = ref / NSEC_PER_SEC;
1604
+ ref -= tod_ns.tv_sec * NSEC_PER_SEC;
1605
+ tod_ns.tv_usec = ref / NSEC_PER_USEC;
1606
+
1607
+ /* Compute clockid time. */
1608
+ ref = ff->ph->env.clock.clockid_ns;
1609
+ clockid_ns.tv_sec = ref / NSEC_PER_SEC;
1610
+ ref -= clockid_ns.tv_sec * NSEC_PER_SEC;
1611
+ clockid_ns.tv_nsec = ref;
1612
+
1613
+ clockid = ff->ph->env.clock.clockid;
1614
+
1615
+ if (localtime_r(&tod_ns.tv_sec, &ltime) == NULL)
1616
+ snprintf(tstr, sizeof(tstr), "<error>");
1617
+ else {
1618
+ strftime(date, sizeof(date), "%F %T", &ltime);
1619
+ scnprintf(tstr, sizeof(tstr), "%s.%06d",
1620
+ date, (int) tod_ns.tv_usec);
1621
+ }
1622
+
1623
+ fprintf(fp, "# clockid: %s (%u)\n", clockid_name(clockid), clockid);
1624
+ fprintf(fp, "# reference time: %s = %ld.%06d (TOD) = %ld.%09ld (%s)\n",
1625
+ tstr, tod_ns.tv_sec, (int) tod_ns.tv_usec,
1626
+ clockid_ns.tv_sec, clockid_ns.tv_nsec,
1627
+ clockid_name(clockid));
1628
+}
1629
+
1630
+static void print_dir_format(struct feat_fd *ff, FILE *fp)
1631
+{
1632
+ struct perf_session *session;
1633
+ struct perf_data *data;
1634
+
1635
+ session = container_of(ff->ph, struct perf_session, header);
1636
+ data = session->data;
1637
+
1638
+ fprintf(fp, "# directory data version : %"PRIu64"\n", data->dir.version);
1639
+}
1640
+
1641
+static void print_bpf_prog_info(struct feat_fd *ff, FILE *fp)
1642
+{
1643
+ struct perf_env *env = &ff->ph->env;
1644
+ struct rb_root *root;
1645
+ struct rb_node *next;
1646
+
1647
+ down_read(&env->bpf_progs.lock);
1648
+
1649
+ root = &env->bpf_progs.infos;
1650
+ next = rb_first(root);
1651
+
1652
+ while (next) {
1653
+ struct bpf_prog_info_node *node;
1654
+
1655
+ node = rb_entry(next, struct bpf_prog_info_node, rb_node);
1656
+ next = rb_next(&node->rb_node);
1657
+
1658
+ bpf_event__print_bpf_prog_info(&node->info_linear->info,
1659
+ env, fp);
1660
+ }
1661
+
1662
+ up_read(&env->bpf_progs.lock);
1663
+}
1664
+
1665
+static void print_bpf_btf(struct feat_fd *ff, FILE *fp)
1666
+{
1667
+ struct perf_env *env = &ff->ph->env;
1668
+ struct rb_root *root;
1669
+ struct rb_node *next;
1670
+
1671
+ down_read(&env->bpf_progs.lock);
1672
+
1673
+ root = &env->bpf_progs.btfs;
1674
+ next = rb_first(root);
1675
+
1676
+ while (next) {
1677
+ struct btf_node *node;
1678
+
1679
+ node = rb_entry(next, struct btf_node, rb_node);
1680
+ next = rb_next(&node->rb_node);
1681
+ fprintf(fp, "# btf info of id %u\n", node->id);
1682
+ }
1683
+
1684
+ up_read(&env->bpf_progs.lock);
1685
+}
1686
+
1687
+static void free_event_desc(struct evsel *events)
1688
+{
1689
+ struct evsel *evsel;
15141690
15151691 if (!events)
15161692 return;
15171693
1518
- for (evsel = events; evsel->attr.size; evsel++) {
1694
+ for (evsel = events; evsel->core.attr.size; evsel++) {
15191695 zfree(&evsel->name);
1520
- zfree(&evsel->id);
1696
+ zfree(&evsel->core.id);
15211697 }
15221698
15231699 free(events);
15241700 }
15251701
1526
-static struct perf_evsel *read_event_desc(struct feat_fd *ff)
1702
+static bool perf_attr_check(struct perf_event_attr *attr)
15271703 {
1528
- struct perf_evsel *evsel, *events = NULL;
1704
+ if (attr->__reserved_1 || attr->__reserved_2 || attr->__reserved_3) {
1705
+ pr_warning("Reserved bits are set unexpectedly. "
1706
+ "Please update perf tool.\n");
1707
+ return false;
1708
+ }
1709
+
1710
+ if (attr->sample_type & ~(PERF_SAMPLE_MAX-1)) {
1711
+ pr_warning("Unknown sample type (0x%llx) is detected. "
1712
+ "Please update perf tool.\n",
1713
+ attr->sample_type);
1714
+ return false;
1715
+ }
1716
+
1717
+ if (attr->read_format & ~(PERF_FORMAT_MAX-1)) {
1718
+ pr_warning("Unknown read format (0x%llx) is detected. "
1719
+ "Please update perf tool.\n",
1720
+ attr->read_format);
1721
+ return false;
1722
+ }
1723
+
1724
+ if ((attr->sample_type & PERF_SAMPLE_BRANCH_STACK) &&
1725
+ (attr->branch_sample_type & ~(PERF_SAMPLE_BRANCH_MAX-1))) {
1726
+ pr_warning("Unknown branch sample type (0x%llx) is detected. "
1727
+ "Please update perf tool.\n",
1728
+ attr->branch_sample_type);
1729
+
1730
+ return false;
1731
+ }
1732
+
1733
+ return true;
1734
+}
1735
+
1736
+static struct evsel *read_event_desc(struct feat_fd *ff)
1737
+{
1738
+ struct evsel *evsel, *events = NULL;
15291739 u64 *id;
15301740 void *buf = NULL;
15311741 u32 nre, sz, nr, i, j;
....@@ -1543,12 +1753,12 @@
15431753 if (!buf)
15441754 goto error;
15451755
1546
- /* the last event terminates with evsel->attr.size == 0: */
1756
+ /* the last event terminates with evsel->core.attr.size == 0: */
15471757 events = calloc(nre + 1, sizeof(*events));
15481758 if (!events)
15491759 goto error;
15501760
1551
- msz = sizeof(evsel->attr);
1761
+ msz = sizeof(evsel->core.attr);
15521762 if (sz < msz)
15531763 msz = sz;
15541764
....@@ -1565,7 +1775,10 @@
15651775 if (ff->ph->needs_swap)
15661776 perf_event__attr_swap(buf);
15671777
1568
- memcpy(&evsel->attr, buf, msz);
1778
+ memcpy(&evsel->core.attr, buf, msz);
1779
+
1780
+ if (!perf_attr_check(&evsel->core.attr))
1781
+ goto error;
15691782
15701783 if (do_read_u32(ff, &nr))
15711784 goto error;
....@@ -1583,8 +1796,8 @@
15831796 id = calloc(nr, sizeof(*id));
15841797 if (!id)
15851798 goto error;
1586
- evsel->ids = nr;
1587
- evsel->id = id;
1799
+ evsel->core.ids = nr;
1800
+ evsel->core.id = id;
15881801
15891802 for (j = 0 ; j < nr; j++) {
15901803 if (do_read_u64(ff, id))
....@@ -1609,7 +1822,7 @@
16091822
16101823 static void print_event_desc(struct feat_fd *ff, FILE *fp)
16111824 {
1612
- struct perf_evsel *evsel, *events;
1825
+ struct evsel *evsel, *events;
16131826 u32 j;
16141827 u64 *id;
16151828
....@@ -1623,12 +1836,12 @@
16231836 return;
16241837 }
16251838
1626
- for (evsel = events; evsel->attr.size; evsel++) {
1839
+ for (evsel = events; evsel->core.attr.size; evsel++) {
16271840 fprintf(fp, "# event : name = %s, ", evsel->name);
16281841
1629
- if (evsel->ids) {
1842
+ if (evsel->core.ids) {
16301843 fprintf(fp, ", id = {");
1631
- for (j = 0, id = evsel->id; j < evsel->ids; j++, id++) {
1844
+ for (j = 0, id = evsel->core.id; j < evsel->core.ids; j++, id++) {
16321845 if (j)
16331846 fputc(',', fp);
16341847 fprintf(fp, " %"PRIu64, *id);
....@@ -1636,7 +1849,7 @@
16361849 fprintf(fp, " }");
16371850 }
16381851
1639
- perf_event_attr__fprintf(fp, &evsel->attr, __desc_attr__fprintf, NULL);
1852
+ perf_event_attr__fprintf(fp, &evsel->core.attr, __desc_attr__fprintf, NULL);
16401853
16411854 fputc('\n', fp);
16421855 }
....@@ -1698,6 +1911,34 @@
16981911 }
16991912 }
17001913
1914
+static void print_compressed(struct feat_fd *ff, FILE *fp)
1915
+{
1916
+ fprintf(fp, "# compressed : %s, level = %d, ratio = %d\n",
1917
+ ff->ph->env.comp_type == PERF_COMP_ZSTD ? "Zstd" : "Unknown",
1918
+ ff->ph->env.comp_level, ff->ph->env.comp_ratio);
1919
+}
1920
+
1921
+static void print_cpu_pmu_caps(struct feat_fd *ff, FILE *fp)
1922
+{
1923
+ const char *delimiter = "# cpu pmu capabilities: ";
1924
+ u32 nr_caps = ff->ph->env.nr_cpu_pmu_caps;
1925
+ char *str;
1926
+
1927
+ if (!nr_caps) {
1928
+ fprintf(fp, "# cpu pmu capabilities: not available\n");
1929
+ return;
1930
+ }
1931
+
1932
+ str = ff->ph->env.cpu_pmu_caps;
1933
+ while (nr_caps--) {
1934
+ fprintf(fp, "%s%s", delimiter, str);
1935
+ delimiter = ", ";
1936
+ str += strlen(str) + 1;
1937
+ }
1938
+
1939
+ fprintf(fp, "\n");
1940
+}
1941
+
17011942 static void print_pmu_mappings(struct feat_fd *ff, FILE *fp)
17021943 {
17031944 const char *delimiter = "# pmu mappings: ";
....@@ -1737,20 +1978,18 @@
17371978 static void print_group_desc(struct feat_fd *ff, FILE *fp)
17381979 {
17391980 struct perf_session *session;
1740
- struct perf_evsel *evsel;
1981
+ struct evsel *evsel;
17411982 u32 nr = 0;
17421983
17431984 session = container_of(ff->ph, struct perf_session, header);
17441985
17451986 evlist__for_each_entry(session->evlist, evsel) {
1746
- if (perf_evsel__is_group_leader(evsel) &&
1747
- evsel->nr_members > 1) {
1748
- fprintf(fp, "# group: %s{%s", evsel->group_name ?: "",
1749
- perf_evsel__name(evsel));
1987
+ if (evsel__is_group_leader(evsel) && evsel->core.nr_members > 1) {
1988
+ fprintf(fp, "# group: %s{%s", evsel->group_name ?: "", evsel__name(evsel));
17501989
1751
- nr = evsel->nr_members - 1;
1990
+ nr = evsel->core.nr_members - 1;
17521991 } else if (nr) {
1753
- fprintf(fp, ",%s", perf_evsel__name(evsel));
1992
+ fprintf(fp, ",%s", evsel__name(evsel));
17541993
17551994 if (--nr == 0)
17561995 fprintf(fp, "}\n");
....@@ -1809,7 +2048,7 @@
18092048 }
18102049 }
18112050
1812
-static int __event_process_build_id(struct build_id_event *bev,
2051
+static int __event_process_build_id(struct perf_record_header_build_id *bev,
18132052 char *filename,
18142053 struct perf_session *session)
18152054 {
....@@ -1817,7 +2056,7 @@
18172056 struct machine *machine;
18182057 u16 cpumode;
18192058 struct dso *dso;
1820
- enum dso_kernel_type dso_type;
2059
+ enum dso_space_type dso_space;
18212060
18222061 machine = perf_session__findnew_machine(session, bev->pid);
18232062 if (!machine)
....@@ -1827,14 +2066,14 @@
18272066
18282067 switch (cpumode) {
18292068 case PERF_RECORD_MISC_KERNEL:
1830
- dso_type = DSO_TYPE_KERNEL;
2069
+ dso_space = DSO_SPACE__KERNEL;
18312070 break;
18322071 case PERF_RECORD_MISC_GUEST_KERNEL:
1833
- dso_type = DSO_TYPE_GUEST_KERNEL;
2072
+ dso_space = DSO_SPACE__KERNEL_GUEST;
18342073 break;
18352074 case PERF_RECORD_MISC_USER:
18362075 case PERF_RECORD_MISC_GUEST_USER:
1837
- dso_type = DSO_TYPE_USER;
2076
+ dso_space = DSO_SPACE__USER;
18382077 break;
18392078 default:
18402079 goto out;
....@@ -1843,24 +2082,28 @@
18432082 dso = machine__findnew_dso(machine, filename);
18442083 if (dso != NULL) {
18452084 char sbuild_id[SBUILD_ID_SIZE];
2085
+ struct build_id bid;
2086
+ size_t size = BUILD_ID_SIZE;
18462087
1847
- dso__set_build_id(dso, &bev->build_id);
2088
+ if (bev->header.misc & PERF_RECORD_MISC_BUILD_ID_SIZE)
2089
+ size = bev->size;
18482090
1849
- if (dso_type != DSO_TYPE_USER) {
2091
+ build_id__init(&bid, bev->data, size);
2092
+ dso__set_build_id(dso, &bid);
2093
+
2094
+ if (dso_space != DSO_SPACE__USER) {
18502095 struct kmod_path m = { .name = NULL, };
18512096
18522097 if (!kmod_path__parse_name(&m, filename) && m.kmod)
18532098 dso__set_module_info(dso, &m, machine);
1854
- else
1855
- dso->kernel = dso_type;
18562099
2100
+ dso->kernel = dso_space;
18572101 free(m.name);
18582102 }
18592103
1860
- build_id__sprintf(dso->build_id, sizeof(dso->build_id),
1861
- sbuild_id);
1862
- pr_debug("build id event received for %s: %s\n",
1863
- dso->long_name, sbuild_id);
2104
+ build_id__sprintf(&dso->bid, sbuild_id);
2105
+ pr_debug("build id event received for %s: %s [%zu]\n",
2106
+ dso->long_name, sbuild_id, size);
18642107 dso__put(dso);
18652108 }
18662109
....@@ -1878,7 +2121,7 @@
18782121 u8 build_id[PERF_ALIGN(BUILD_ID_SIZE, sizeof(u64))];
18792122 char filename[0];
18802123 } old_bev;
1881
- struct build_id_event bev;
2124
+ struct perf_record_header_build_id bev;
18822125 char filename[PATH_MAX];
18832126 u64 limit = offset + size;
18842127
....@@ -1919,7 +2162,7 @@
19192162 int input, u64 offset, u64 size)
19202163 {
19212164 struct perf_session *session = container_of(header, struct perf_session, header);
1922
- struct build_id_event bev;
2165
+ struct perf_record_header_build_id bev;
19232166 char filename[PATH_MAX];
19242167 u64 limit = offset + size, orig_offset = offset;
19252168 int err = -1;
....@@ -1941,7 +2184,7 @@
19412184 *
19422185 * "perf: 'perf kvm' tool for monitoring guest performance from host"
19432186 *
1944
- * Added a field to struct build_id_event that broke the file
2187
+ * Added a field to struct perf_record_header_build_id that broke the file
19452188 * format.
19462189 *
19472190 * Since the kernel build-id is the first entry, process the
....@@ -2022,10 +2265,10 @@
20222265 return 0;
20232266 }
20242267
2025
-static struct perf_evsel *
2026
-perf_evlist__find_by_index(struct perf_evlist *evlist, int idx)
2268
+static struct evsel *
2269
+perf_evlist__find_by_index(struct evlist *evlist, int idx)
20272270 {
2028
- struct perf_evsel *evsel;
2271
+ struct evsel *evsel;
20292272
20302273 evlist__for_each_entry(evlist, evsel) {
20312274 if (evsel->idx == idx)
....@@ -2036,10 +2279,10 @@
20362279 }
20372280
20382281 static void
2039
-perf_evlist__set_event_name(struct perf_evlist *evlist,
2040
- struct perf_evsel *event)
2282
+perf_evlist__set_event_name(struct evlist *evlist,
2283
+ struct evsel *event)
20412284 {
2042
- struct perf_evsel *evsel;
2285
+ struct evsel *evsel;
20432286
20442287 if (!event->name)
20452288 return;
....@@ -2058,7 +2301,7 @@
20582301 process_event_desc(struct feat_fd *ff, void *data __maybe_unused)
20592302 {
20602303 struct perf_session *session;
2061
- struct perf_evsel *evsel, *events = read_event_desc(ff);
2304
+ struct evsel *evsel, *events = read_event_desc(ff);
20622305
20632306 if (!events)
20642307 return 0;
....@@ -2071,7 +2314,7 @@
20712314 ff->events = events;
20722315 }
20732316
2074
- for (evsel = events; evsel->attr.size; evsel++)
2317
+ for (evsel = events; evsel->core.attr.size; evsel++)
20752318 perf_evlist__set_event_name(session->evlist, evsel);
20762319
20772320 if (!session->data->is_pipe)
....@@ -2195,6 +2438,7 @@
21952438 goto free_cpu;
21962439
21972440 ph->env.cpu[i].core_id = nr;
2441
+ size += sizeof(u32);
21982442
21992443 if (do_read_u32(ff, &nr))
22002444 goto free_cpu;
....@@ -2206,6 +2450,40 @@
22062450 }
22072451
22082452 ph->env.cpu[i].socket_id = nr;
2453
+ size += sizeof(u32);
2454
+ }
2455
+
2456
+ /*
2457
+ * The header may be from old perf,
2458
+ * which doesn't include die information.
2459
+ */
2460
+ if (ff->size <= size)
2461
+ return 0;
2462
+
2463
+ if (do_read_u32(ff, &nr))
2464
+ return -1;
2465
+
2466
+ ph->env.nr_sibling_dies = nr;
2467
+ size += sizeof(u32);
2468
+
2469
+ for (i = 0; i < nr; i++) {
2470
+ str = do_read_string(ff);
2471
+ if (!str)
2472
+ goto error;
2473
+
2474
+ /* include a NULL character at the end */
2475
+ if (strbuf_add(&sb, str, strlen(str) + 1) < 0)
2476
+ goto error;
2477
+ size += string_size(str);
2478
+ free(str);
2479
+ }
2480
+ ph->env.sibling_dies = strbuf_detach(&sb, NULL);
2481
+
2482
+ for (i = 0; i < (u32)cpu_nr; i++) {
2483
+ if (do_read_u32(ff, &nr))
2484
+ goto free_cpu;
2485
+
2486
+ ph->env.cpu[i].die_id = nr;
22092487 }
22102488
22112489 return 0;
....@@ -2248,7 +2526,7 @@
22482526 if (!str)
22492527 goto error;
22502528
2251
- n->map = cpu_map__new(str);
2529
+ n->map = perf_cpu_map__new(str);
22522530 if (!n->map)
22532531 goto error;
22542532
....@@ -2315,7 +2593,7 @@
23152593 size_t ret = -1;
23162594 u32 i, nr, nr_groups;
23172595 struct perf_session *session;
2318
- struct perf_evsel *evsel, *leader = NULL;
2596
+ struct evsel *evsel, *leader = NULL;
23192597 struct group_desc {
23202598 char *name;
23212599 u32 leader_idx;
....@@ -2362,7 +2640,7 @@
23622640 evsel->group_name = desc[i].name;
23632641 desc[i].name = NULL;
23642642 }
2365
- evsel->nr_members = desc[i].nr_members;
2643
+ evsel->core.nr_members = desc[i].nr_members;
23662644
23672645 if (i >= nr_groups || nr > 0) {
23682646 pr_debug("invalid group desc\n");
....@@ -2370,7 +2648,7 @@
23702648 }
23712649
23722650 leader = evsel;
2373
- nr = evsel->nr_members - 1;
2651
+ nr = evsel->core.nr_members - 1;
23742652 i++;
23752653 } else if (nr) {
23762654 /* This is a group member */
....@@ -2533,14 +2811,260 @@
25332811 return ret;
25342812 }
25352813
2536
-struct feature_ops {
2537
- int (*write)(struct feat_fd *ff, struct perf_evlist *evlist);
2538
- void (*print)(struct feat_fd *ff, FILE *fp);
2539
- int (*process)(struct feat_fd *ff, void *data);
2540
- const char *name;
2541
- bool full_only;
2542
- bool synthesize;
2543
-};
2814
+static int process_clockid(struct feat_fd *ff,
2815
+ void *data __maybe_unused)
2816
+{
2817
+ if (do_read_u64(ff, &ff->ph->env.clock.clockid_res_ns))
2818
+ return -1;
2819
+
2820
+ return 0;
2821
+}
2822
+
2823
+static int process_clock_data(struct feat_fd *ff,
2824
+ void *_data __maybe_unused)
2825
+{
2826
+ u32 data32;
2827
+ u64 data64;
2828
+
2829
+ /* version */
2830
+ if (do_read_u32(ff, &data32))
2831
+ return -1;
2832
+
2833
+ if (data32 != 1)
2834
+ return -1;
2835
+
2836
+ /* clockid */
2837
+ if (do_read_u32(ff, &data32))
2838
+ return -1;
2839
+
2840
+ ff->ph->env.clock.clockid = data32;
2841
+
2842
+ /* TOD ref time */
2843
+ if (do_read_u64(ff, &data64))
2844
+ return -1;
2845
+
2846
+ ff->ph->env.clock.tod_ns = data64;
2847
+
2848
+ /* clockid ref time */
2849
+ if (do_read_u64(ff, &data64))
2850
+ return -1;
2851
+
2852
+ ff->ph->env.clock.clockid_ns = data64;
2853
+ ff->ph->env.clock.enabled = true;
2854
+ return 0;
2855
+}
2856
+
2857
+static int process_dir_format(struct feat_fd *ff,
2858
+ void *_data __maybe_unused)
2859
+{
2860
+ struct perf_session *session;
2861
+ struct perf_data *data;
2862
+
2863
+ session = container_of(ff->ph, struct perf_session, header);
2864
+ data = session->data;
2865
+
2866
+ if (WARN_ON(!perf_data__is_dir(data)))
2867
+ return -1;
2868
+
2869
+ return do_read_u64(ff, &data->dir.version);
2870
+}
2871
+
2872
+#ifdef HAVE_LIBBPF_SUPPORT
2873
+static int process_bpf_prog_info(struct feat_fd *ff, void *data __maybe_unused)
2874
+{
2875
+ struct bpf_prog_info_linear *info_linear;
2876
+ struct bpf_prog_info_node *info_node;
2877
+ struct perf_env *env = &ff->ph->env;
2878
+ u32 count, i;
2879
+ int err = -1;
2880
+
2881
+ if (ff->ph->needs_swap) {
2882
+ pr_warning("interpreting bpf_prog_info from systems with endianity is not yet supported\n");
2883
+ return 0;
2884
+ }
2885
+
2886
+ if (do_read_u32(ff, &count))
2887
+ return -1;
2888
+
2889
+ down_write(&env->bpf_progs.lock);
2890
+
2891
+ for (i = 0; i < count; ++i) {
2892
+ u32 info_len, data_len;
2893
+
2894
+ info_linear = NULL;
2895
+ info_node = NULL;
2896
+ if (do_read_u32(ff, &info_len))
2897
+ goto out;
2898
+ if (do_read_u32(ff, &data_len))
2899
+ goto out;
2900
+
2901
+ if (info_len > sizeof(struct bpf_prog_info)) {
2902
+ pr_warning("detected invalid bpf_prog_info\n");
2903
+ goto out;
2904
+ }
2905
+
2906
+ info_linear = malloc(sizeof(struct bpf_prog_info_linear) +
2907
+ data_len);
2908
+ if (!info_linear)
2909
+ goto out;
2910
+ info_linear->info_len = sizeof(struct bpf_prog_info);
2911
+ info_linear->data_len = data_len;
2912
+ if (do_read_u64(ff, (u64 *)(&info_linear->arrays)))
2913
+ goto out;
2914
+ if (__do_read(ff, &info_linear->info, info_len))
2915
+ goto out;
2916
+ if (info_len < sizeof(struct bpf_prog_info))
2917
+ memset(((void *)(&info_linear->info)) + info_len, 0,
2918
+ sizeof(struct bpf_prog_info) - info_len);
2919
+
2920
+ if (__do_read(ff, info_linear->data, data_len))
2921
+ goto out;
2922
+
2923
+ info_node = malloc(sizeof(struct bpf_prog_info_node));
2924
+ if (!info_node)
2925
+ goto out;
2926
+
2927
+ /* after reading from file, translate offset to address */
2928
+ bpf_program__bpil_offs_to_addr(info_linear);
2929
+ info_node->info_linear = info_linear;
2930
+ perf_env__insert_bpf_prog_info(env, info_node);
2931
+ }
2932
+
2933
+ up_write(&env->bpf_progs.lock);
2934
+ return 0;
2935
+out:
2936
+ free(info_linear);
2937
+ free(info_node);
2938
+ up_write(&env->bpf_progs.lock);
2939
+ return err;
2940
+}
2941
+#else // HAVE_LIBBPF_SUPPORT
2942
+static int process_bpf_prog_info(struct feat_fd *ff __maybe_unused, void *data __maybe_unused)
2943
+{
2944
+ return 0;
2945
+}
2946
+#endif // HAVE_LIBBPF_SUPPORT
2947
+
2948
+static int process_bpf_btf(struct feat_fd *ff, void *data __maybe_unused)
2949
+{
2950
+ struct perf_env *env = &ff->ph->env;
2951
+ struct btf_node *node = NULL;
2952
+ u32 count, i;
2953
+ int err = -1;
2954
+
2955
+ if (ff->ph->needs_swap) {
2956
+ pr_warning("interpreting btf from systems with endianity is not yet supported\n");
2957
+ return 0;
2958
+ }
2959
+
2960
+ if (do_read_u32(ff, &count))
2961
+ return -1;
2962
+
2963
+ down_write(&env->bpf_progs.lock);
2964
+
2965
+ for (i = 0; i < count; ++i) {
2966
+ u32 id, data_size;
2967
+
2968
+ if (do_read_u32(ff, &id))
2969
+ goto out;
2970
+ if (do_read_u32(ff, &data_size))
2971
+ goto out;
2972
+
2973
+ node = malloc(sizeof(struct btf_node) + data_size);
2974
+ if (!node)
2975
+ goto out;
2976
+
2977
+ node->id = id;
2978
+ node->data_size = data_size;
2979
+
2980
+ if (__do_read(ff, node->data, data_size))
2981
+ goto out;
2982
+
2983
+ perf_env__insert_btf(env, node);
2984
+ node = NULL;
2985
+ }
2986
+
2987
+ err = 0;
2988
+out:
2989
+ up_write(&env->bpf_progs.lock);
2990
+ free(node);
2991
+ return err;
2992
+}
2993
+
2994
+static int process_compressed(struct feat_fd *ff,
2995
+ void *data __maybe_unused)
2996
+{
2997
+ if (do_read_u32(ff, &(ff->ph->env.comp_ver)))
2998
+ return -1;
2999
+
3000
+ if (do_read_u32(ff, &(ff->ph->env.comp_type)))
3001
+ return -1;
3002
+
3003
+ if (do_read_u32(ff, &(ff->ph->env.comp_level)))
3004
+ return -1;
3005
+
3006
+ if (do_read_u32(ff, &(ff->ph->env.comp_ratio)))
3007
+ return -1;
3008
+
3009
+ if (do_read_u32(ff, &(ff->ph->env.comp_mmap_len)))
3010
+ return -1;
3011
+
3012
+ return 0;
3013
+}
3014
+
3015
+static int process_cpu_pmu_caps(struct feat_fd *ff,
3016
+ void *data __maybe_unused)
3017
+{
3018
+ char *name, *value;
3019
+ struct strbuf sb;
3020
+ u32 nr_caps;
3021
+
3022
+ if (do_read_u32(ff, &nr_caps))
3023
+ return -1;
3024
+
3025
+ if (!nr_caps) {
3026
+ pr_debug("cpu pmu capabilities not available\n");
3027
+ return 0;
3028
+ }
3029
+
3030
+ ff->ph->env.nr_cpu_pmu_caps = nr_caps;
3031
+
3032
+ if (strbuf_init(&sb, 128) < 0)
3033
+ return -1;
3034
+
3035
+ while (nr_caps--) {
3036
+ name = do_read_string(ff);
3037
+ if (!name)
3038
+ goto error;
3039
+
3040
+ value = do_read_string(ff);
3041
+ if (!value)
3042
+ goto free_name;
3043
+
3044
+ if (strbuf_addf(&sb, "%s=%s", name, value) < 0)
3045
+ goto free_value;
3046
+
3047
+ /* include a NULL character at the end */
3048
+ if (strbuf_add(&sb, "", 1) < 0)
3049
+ goto free_value;
3050
+
3051
+ if (!strcmp(name, "branches"))
3052
+ ff->ph->env.max_branches = atoi(value);
3053
+
3054
+ free(value);
3055
+ free(name);
3056
+ }
3057
+ ff->ph->env.cpu_pmu_caps = strbuf_detach(&sb, NULL);
3058
+ return 0;
3059
+
3060
+free_value:
3061
+ free(value);
3062
+free_name:
3063
+ free(name);
3064
+error:
3065
+ strbuf_release(&sb);
3066
+ return -1;
3067
+}
25443068
25453069 #define FEAT_OPR(n, func, __full_only) \
25463070 [HEADER_##n] = { \
....@@ -2568,8 +3092,10 @@
25683092 #define process_branch_stack NULL
25693093 #define process_stat NULL
25703094
3095
+// Only used in util/synthetic-events.c
3096
+const struct perf_header_feature_ops feat_ops[HEADER_LAST_FEATURE];
25713097
2572
-static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
3098
+const struct perf_header_feature_ops feat_ops[HEADER_LAST_FEATURE] = {
25733099 FEAT_OPN(TRACING_DATA, tracing_data, false),
25743100 FEAT_OPN(BUILD_ID, build_id, false),
25753101 FEAT_OPR(HOSTNAME, hostname, false),
....@@ -2592,6 +3118,13 @@
25923118 FEAT_OPN(CACHE, cache, true),
25933119 FEAT_OPR(SAMPLE_TIME, sample_time, false),
25943120 FEAT_OPR(MEM_TOPOLOGY, mem_topology, true),
3121
+ FEAT_OPR(CLOCKID, clockid, false),
3122
+ FEAT_OPN(DIR_FORMAT, dir_format, false),
3123
+ FEAT_OPR(BPF_PROG_INFO, bpf_prog_info, false),
3124
+ FEAT_OPR(BPF_BTF, bpf_btf, false),
3125
+ FEAT_OPR(COMPRESSED, compressed, false),
3126
+ FEAT_OPR(CPU_PMU_CAPS, cpu_pmu_caps, false),
3127
+ FEAT_OPR(CLOCK_DATA, clock_data, false),
25953128 };
25963129
25973130 struct header_print_data {
....@@ -2648,7 +3181,7 @@
26483181 if (ret == -1)
26493182 return -1;
26503183
2651
- stctime = st.st_ctime;
3184
+ stctime = st.st_mtime;
26523185 fprintf(fp, "# captured on : %s", ctime(&stctime));
26533186
26543187 fprintf(fp, "# header version : %u\n", header->version);
....@@ -2674,7 +3207,7 @@
26743207
26753208 static int do_write_feat(struct feat_fd *ff, int type,
26763209 struct perf_file_section **p,
2677
- struct perf_evlist *evlist)
3210
+ struct evlist *evlist)
26783211 {
26793212 int err;
26803213 int ret = 0;
....@@ -2704,7 +3237,7 @@
27043237 }
27053238
27063239 static int perf_header__adds_write(struct perf_header *header,
2707
- struct perf_evlist *evlist, int fd)
3240
+ struct evlist *evlist, int fd)
27083241 {
27093242 int nr_sections;
27103243 struct feat_fd ff;
....@@ -2740,7 +3273,7 @@
27403273 lseek(fd, sec_start, SEEK_SET);
27413274 /*
27423275 * may write more than needed due to dropped feature, but
2743
- * this is okay, reader will skip the mising entries
3276
+ * this is okay, reader will skip the missing entries
27443277 */
27453278 err = do_write(&ff, feat_sec, sec_size);
27463279 if (err < 0)
....@@ -2772,13 +3305,13 @@
27723305 }
27733306
27743307 int perf_session__write_header(struct perf_session *session,
2775
- struct perf_evlist *evlist,
3308
+ struct evlist *evlist,
27763309 int fd, bool at_exit)
27773310 {
27783311 struct perf_file_header f_header;
27793312 struct perf_file_attr f_attr;
27803313 struct perf_header *header = &session->header;
2781
- struct perf_evsel *evsel;
3314
+ struct evsel *evsel;
27823315 struct feat_fd ff;
27833316 u64 attr_offset;
27843317 int err;
....@@ -2788,7 +3321,7 @@
27883321
27893322 evlist__for_each_entry(session->evlist, evsel) {
27903323 evsel->id_offset = lseek(fd, 0, SEEK_CUR);
2791
- err = do_write(&ff, evsel->id, evsel->ids * sizeof(u64));
3324
+ err = do_write(&ff, evsel->core.id, evsel->core.ids * sizeof(u64));
27923325 if (err < 0) {
27933326 pr_debug("failed to write perf header\n");
27943327 return err;
....@@ -2799,10 +3332,10 @@
27993332
28003333 evlist__for_each_entry(evlist, evsel) {
28013334 f_attr = (struct perf_file_attr){
2802
- .attr = evsel->attr,
3335
+ .attr = evsel->core.attr,
28033336 .ids = {
28043337 .offset = evsel->id_offset,
2805
- .size = evsel->ids * sizeof(u64),
3338
+ .size = evsel->core.ids * sizeof(u64),
28063339 }
28073340 };
28083341 err = do_write(&ff, &f_attr, sizeof(f_attr));
....@@ -2828,7 +3361,7 @@
28283361 .attr_size = sizeof(f_attr),
28293362 .attrs = {
28303363 .offset = attr_offset,
2831
- .size = evlist->nr_entries * sizeof(f_attr),
3364
+ .size = evlist->core.nr_entries * sizeof(f_attr),
28323365 },
28333366 .data = {
28343367 .offset = header->data_offset,
....@@ -3158,7 +3691,7 @@
31583691 return -EINVAL;
31593692 }
31603693
3161
- return 0;
3694
+ return f_header.size == sizeof(f_header) ? 0 : -1;
31623695 }
31633696
31643697 static int read_attr(int fd, struct perf_header *ph,
....@@ -3207,10 +3740,10 @@
32073740 return ret <= 0 ? -1 : 0;
32083741 }
32093742
3210
-static int perf_evsel__prepare_tracepoint_event(struct perf_evsel *evsel,
3743
+static int perf_evsel__prepare_tracepoint_event(struct evsel *evsel,
32113744 struct tep_handle *pevent)
32123745 {
3213
- struct event_format *event;
3746
+ struct tep_event *event;
32143747 char bf[128];
32153748
32163749 /* already prepared */
....@@ -3222,9 +3755,9 @@
32223755 return -1;
32233756 }
32243757
3225
- event = tep_find_event(pevent, evsel->attr.config);
3758
+ event = tep_find_event(pevent, evsel->core.attr.config);
32263759 if (event == NULL) {
3227
- pr_debug("cannot find event format for %d\n", (int)evsel->attr.config);
3760
+ pr_debug("cannot find event format for %d\n", (int)evsel->core.attr.config);
32283761 return -1;
32293762 }
32303763
....@@ -3239,13 +3772,13 @@
32393772 return 0;
32403773 }
32413774
3242
-static int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist,
3775
+static int perf_evlist__prepare_tracepoint_events(struct evlist *evlist,
32433776 struct tep_handle *pevent)
32443777 {
3245
- struct perf_evsel *pos;
3778
+ struct evsel *pos;
32463779
32473780 evlist__for_each_entry(evlist, pos) {
3248
- if (pos->attr.type == PERF_TYPE_TRACEPOINT &&
3781
+ if (pos->core.attr.type == PERF_TYPE_TRACEPOINT &&
32493782 perf_evsel__prepare_tracepoint_event(pos, pevent))
32503783 return -1;
32513784 }
....@@ -3260,17 +3793,25 @@
32603793 struct perf_file_header f_header;
32613794 struct perf_file_attr f_attr;
32623795 u64 f_id;
3263
- int nr_attrs, nr_ids, i, j;
3796
+ int nr_attrs, nr_ids, i, j, err;
32643797 int fd = perf_data__fd(data);
32653798
3266
- session->evlist = perf_evlist__new();
3799
+ session->evlist = evlist__new();
32673800 if (session->evlist == NULL)
32683801 return -ENOMEM;
32693802
32703803 session->evlist->env = &header->env;
32713804 session->machines.host.env = &header->env;
3272
- if (perf_data__is_pipe(data))
3273
- return perf_header__read_pipe(session);
3805
+
3806
+ /*
3807
+ * We can read 'pipe' data event from regular file,
3808
+ * check for the pipe header regardless of source.
3809
+ */
3810
+ err = perf_header__read_pipe(session);
3811
+ if (!err || (err && perf_data__is_pipe(data))) {
3812
+ data->is_pipe = true;
3813
+ return err;
3814
+ }
32743815
32753816 if (perf_file_header__read(&f_header, header, fd) < 0)
32763817 return -EINVAL;
....@@ -3298,7 +3839,7 @@
32983839 lseek(fd, f_header.attrs.offset, SEEK_SET);
32993840
33003841 for (i = 0; i < nr_attrs; i++) {
3301
- struct perf_evsel *evsel;
3842
+ struct evsel *evsel;
33023843 off_t tmp;
33033844
33043845 if (read_attr(fd, header, &f_attr) < 0)
....@@ -3311,7 +3852,7 @@
33113852 }
33123853
33133854 tmp = lseek(fd, 0, SEEK_CUR);
3314
- evsel = perf_evsel__new(&f_attr.attr);
3855
+ evsel = evsel__new(&f_attr.attr);
33153856
33163857 if (evsel == NULL)
33173858 goto out_delete_evlist;
....@@ -3319,9 +3860,9 @@
33193860 evsel->needs_swap = header->needs_swap;
33203861 /*
33213862 * Do it before so that if perf_evsel__alloc_id fails, this
3322
- * entry gets purged too at perf_evlist__delete().
3863
+ * entry gets purged too at evlist__delete().
33233864 */
3324
- perf_evlist__add(session->evlist, evsel);
3865
+ evlist__add(session->evlist, evsel);
33253866
33263867 nr_ids = f_attr.ids.size / sizeof(u64);
33273868 /*
....@@ -3329,7 +3870,7 @@
33293870 * for allocating the perf_sample_id table we fake 1 cpu and
33303871 * hattr->ids threads.
33313872 */
3332
- if (perf_evsel__alloc_id(evsel, 1, nr_ids))
3873
+ if (perf_evsel__alloc_id(&evsel->core, 1, nr_ids))
33333874 goto out_delete_evlist;
33343875
33353876 lseek(fd, f_attr.ids.offset, SEEK_SET);
....@@ -3338,7 +3879,7 @@
33383879 if (perf_header__getbuffer64(header, fd, &f_id, sizeof(f_id)))
33393880 goto out_errno;
33403881
3341
- perf_evlist__id_add(session->evlist, evsel, 0, j, f_id);
3882
+ perf_evlist__id_add(&session->evlist->core, &evsel->core, 0, j, f_id);
33423883 }
33433884
33443885 lseek(fd, tmp, SEEK_SET);
....@@ -3356,115 +3897,17 @@
33563897 return -errno;
33573898
33583899 out_delete_evlist:
3359
- perf_evlist__delete(session->evlist);
3900
+ evlist__delete(session->evlist);
33603901 session->evlist = NULL;
33613902 return -ENOMEM;
33623903 }
33633904
3364
-int perf_event__synthesize_attr(struct perf_tool *tool,
3365
- struct perf_event_attr *attr, u32 ids, u64 *id,
3366
- perf_event__handler_t process)
3905
+int perf_event__process_feature(struct perf_session *session,
3906
+ union perf_event *event)
33673907 {
3368
- union perf_event *ev;
3369
- size_t size;
3370
- int err;
3371
-
3372
- size = sizeof(struct perf_event_attr);
3373
- size = PERF_ALIGN(size, sizeof(u64));
3374
- size += sizeof(struct perf_event_header);
3375
- size += ids * sizeof(u64);
3376
-
3377
- ev = zalloc(size);
3378
-
3379
- if (ev == NULL)
3380
- return -ENOMEM;
3381
-
3382
- ev->attr.attr = *attr;
3383
- memcpy(ev->attr.id, id, ids * sizeof(u64));
3384
-
3385
- ev->attr.header.type = PERF_RECORD_HEADER_ATTR;
3386
- ev->attr.header.size = (u16)size;
3387
-
3388
- if (ev->attr.header.size == size)
3389
- err = process(tool, ev, NULL, NULL);
3390
- else
3391
- err = -E2BIG;
3392
-
3393
- free(ev);
3394
-
3395
- return err;
3396
-}
3397
-
3398
-int perf_event__synthesize_features(struct perf_tool *tool,
3399
- struct perf_session *session,
3400
- struct perf_evlist *evlist,
3401
- perf_event__handler_t process)
3402
-{
3403
- struct perf_header *header = &session->header;
3404
- struct feat_fd ff;
3405
- struct feature_event *fe;
3406
- size_t sz, sz_hdr;
3407
- int feat, ret;
3408
-
3409
- sz_hdr = sizeof(fe->header);
3410
- sz = sizeof(union perf_event);
3411
- /* get a nice alignment */
3412
- sz = PERF_ALIGN(sz, page_size);
3413
-
3414
- memset(&ff, 0, sizeof(ff));
3415
-
3416
- ff.buf = malloc(sz);
3417
- if (!ff.buf)
3418
- return -ENOMEM;
3419
-
3420
- ff.size = sz - sz_hdr;
3421
-
3422
- for_each_set_bit(feat, header->adds_features, HEADER_FEAT_BITS) {
3423
- if (!feat_ops[feat].synthesize) {
3424
- pr_debug("No record header feature for header :%d\n", feat);
3425
- continue;
3426
- }
3427
-
3428
- ff.offset = sizeof(*fe);
3429
-
3430
- ret = feat_ops[feat].write(&ff, evlist);
3431
- if (ret || ff.offset <= (ssize_t)sizeof(*fe)) {
3432
- pr_debug("Error writing feature\n");
3433
- continue;
3434
- }
3435
- /* ff.buf may have changed due to realloc in do_write() */
3436
- fe = ff.buf;
3437
- memset(fe, 0, sizeof(*fe));
3438
-
3439
- fe->feat_id = feat;
3440
- fe->header.type = PERF_RECORD_HEADER_FEATURE;
3441
- fe->header.size = ff.offset;
3442
-
3443
- ret = process(tool, ff.buf, NULL, NULL);
3444
- if (ret) {
3445
- free(ff.buf);
3446
- return ret;
3447
- }
3448
- }
3449
-
3450
- /* Send HEADER_LAST_FEATURE mark. */
3451
- fe = ff.buf;
3452
- fe->feat_id = HEADER_LAST_FEATURE;
3453
- fe->header.type = PERF_RECORD_HEADER_FEATURE;
3454
- fe->header.size = sizeof(*fe);
3455
-
3456
- ret = process(tool, ff.buf, NULL, NULL);
3457
-
3458
- free(ff.buf);
3459
- return ret;
3460
-}
3461
-
3462
-int perf_event__process_feature(struct perf_tool *tool,
3463
- union perf_event *event,
3464
- struct perf_session *session __maybe_unused)
3465
-{
3908
+ struct perf_tool *tool = session->tool;
34663909 struct feat_fd ff = { .fd = 0 };
3467
- struct feature_event *fe = (struct feature_event *)event;
3910
+ struct perf_record_header_feature *fe = (struct perf_record_header_feature *)event;
34683911 int type = fe->header.type;
34693912 u64 feat = fe->feat_id;
34703913
....@@ -3501,126 +3944,19 @@
35013944 return 0;
35023945 }
35033946
3504
-static struct event_update_event *
3505
-event_update_event__new(size_t size, u64 type, u64 id)
3506
-{
3507
- struct event_update_event *ev;
3508
-
3509
- size += sizeof(*ev);
3510
- size = PERF_ALIGN(size, sizeof(u64));
3511
-
3512
- ev = zalloc(size);
3513
- if (ev) {
3514
- ev->header.type = PERF_RECORD_EVENT_UPDATE;
3515
- ev->header.size = (u16)size;
3516
- ev->type = type;
3517
- ev->id = id;
3518
- }
3519
- return ev;
3520
-}
3521
-
3522
-int
3523
-perf_event__synthesize_event_update_unit(struct perf_tool *tool,
3524
- struct perf_evsel *evsel,
3525
- perf_event__handler_t process)
3526
-{
3527
- struct event_update_event *ev;
3528
- size_t size = strlen(evsel->unit);
3529
- int err;
3530
-
3531
- ev = event_update_event__new(size + 1, PERF_EVENT_UPDATE__UNIT, evsel->id[0]);
3532
- if (ev == NULL)
3533
- return -ENOMEM;
3534
-
3535
- strlcpy(ev->data, evsel->unit, size + 1);
3536
- err = process(tool, (union perf_event *)ev, NULL, NULL);
3537
- free(ev);
3538
- return err;
3539
-}
3540
-
3541
-int
3542
-perf_event__synthesize_event_update_scale(struct perf_tool *tool,
3543
- struct perf_evsel *evsel,
3544
- perf_event__handler_t process)
3545
-{
3546
- struct event_update_event *ev;
3547
- struct event_update_event_scale *ev_data;
3548
- int err;
3549
-
3550
- ev = event_update_event__new(sizeof(*ev_data), PERF_EVENT_UPDATE__SCALE, evsel->id[0]);
3551
- if (ev == NULL)
3552
- return -ENOMEM;
3553
-
3554
- ev_data = (struct event_update_event_scale *) ev->data;
3555
- ev_data->scale = evsel->scale;
3556
- err = process(tool, (union perf_event*) ev, NULL, NULL);
3557
- free(ev);
3558
- return err;
3559
-}
3560
-
3561
-int
3562
-perf_event__synthesize_event_update_name(struct perf_tool *tool,
3563
- struct perf_evsel *evsel,
3564
- perf_event__handler_t process)
3565
-{
3566
- struct event_update_event *ev;
3567
- size_t len = strlen(evsel->name);
3568
- int err;
3569
-
3570
- ev = event_update_event__new(len + 1, PERF_EVENT_UPDATE__NAME, evsel->id[0]);
3571
- if (ev == NULL)
3572
- return -ENOMEM;
3573
-
3574
- strlcpy(ev->data, evsel->name, len + 1);
3575
- err = process(tool, (union perf_event*) ev, NULL, NULL);
3576
- free(ev);
3577
- return err;
3578
-}
3579
-
3580
-int
3581
-perf_event__synthesize_event_update_cpus(struct perf_tool *tool,
3582
- struct perf_evsel *evsel,
3583
- perf_event__handler_t process)
3584
-{
3585
- size_t size = sizeof(struct event_update_event);
3586
- struct event_update_event *ev;
3587
- int max, err;
3588
- u16 type;
3589
-
3590
- if (!evsel->own_cpus)
3591
- return 0;
3592
-
3593
- ev = cpu_map_data__alloc(evsel->own_cpus, &size, &type, &max);
3594
- if (!ev)
3595
- return -ENOMEM;
3596
-
3597
- ev->header.type = PERF_RECORD_EVENT_UPDATE;
3598
- ev->header.size = (u16)size;
3599
- ev->type = PERF_EVENT_UPDATE__CPUS;
3600
- ev->id = evsel->id[0];
3601
-
3602
- cpu_map_data__synthesize((struct cpu_map_data *) ev->data,
3603
- evsel->own_cpus,
3604
- type, max);
3605
-
3606
- err = process(tool, (union perf_event*) ev, NULL, NULL);
3607
- free(ev);
3608
- return err;
3609
-}
3610
-
36113947 size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp)
36123948 {
3613
- struct event_update_event *ev = &event->event_update;
3614
- struct event_update_event_scale *ev_scale;
3615
- struct event_update_event_cpus *ev_cpus;
3616
- struct cpu_map *map;
3949
+ struct perf_record_event_update *ev = &event->event_update;
3950
+ struct perf_record_event_update_scale *ev_scale;
3951
+ struct perf_record_event_update_cpus *ev_cpus;
3952
+ struct perf_cpu_map *map;
36173953 size_t ret;
36183954
3619
- ret = fprintf(fp, "\n... id: %" PRIu64 "\n", ev->id);
3955
+ ret = fprintf(fp, "\n... id: %" PRI_lu64 "\n", ev->id);
36203956
36213957 switch (ev->type) {
36223958 case PERF_EVENT_UPDATE__SCALE:
3623
- ev_scale = (struct event_update_event_scale *) ev->data;
3959
+ ev_scale = (struct perf_record_event_update_scale *)ev->data;
36243960 ret += fprintf(fp, "... scale: %f\n", ev_scale->scale);
36253961 break;
36263962 case PERF_EVENT_UPDATE__UNIT:
....@@ -3630,7 +3966,7 @@
36303966 ret += fprintf(fp, "... name: %s\n", ev->data);
36313967 break;
36323968 case PERF_EVENT_UPDATE__CPUS:
3633
- ev_cpus = (struct event_update_event_cpus *) ev->data;
3969
+ ev_cpus = (struct perf_record_event_update_cpus *)ev->data;
36343970 ret += fprintf(fp, "... ");
36353971
36363972 map = cpu_map__new_data(&ev_cpus->cpus);
....@@ -3647,112 +3983,25 @@
36473983 return ret;
36483984 }
36493985
3650
-int perf_event__synthesize_attrs(struct perf_tool *tool,
3651
- struct perf_session *session,
3652
- perf_event__handler_t process)
3653
-{
3654
- struct perf_evsel *evsel;
3655
- int err = 0;
3656
-
3657
- evlist__for_each_entry(session->evlist, evsel) {
3658
- err = perf_event__synthesize_attr(tool, &evsel->attr, evsel->ids,
3659
- evsel->id, process);
3660
- if (err) {
3661
- pr_debug("failed to create perf header attribute\n");
3662
- return err;
3663
- }
3664
- }
3665
-
3666
- return err;
3667
-}
3668
-
3669
-static bool has_unit(struct perf_evsel *counter)
3670
-{
3671
- return counter->unit && *counter->unit;
3672
-}
3673
-
3674
-static bool has_scale(struct perf_evsel *counter)
3675
-{
3676
- return counter->scale != 1;
3677
-}
3678
-
3679
-int perf_event__synthesize_extra_attr(struct perf_tool *tool,
3680
- struct perf_evlist *evsel_list,
3681
- perf_event__handler_t process,
3682
- bool is_pipe)
3683
-{
3684
- struct perf_evsel *counter;
3685
- int err;
3686
-
3687
- /*
3688
- * Synthesize other events stuff not carried within
3689
- * attr event - unit, scale, name
3690
- */
3691
- evlist__for_each_entry(evsel_list, counter) {
3692
- if (!counter->supported)
3693
- continue;
3694
-
3695
- /*
3696
- * Synthesize unit and scale only if it's defined.
3697
- */
3698
- if (has_unit(counter)) {
3699
- err = perf_event__synthesize_event_update_unit(tool, counter, process);
3700
- if (err < 0) {
3701
- pr_err("Couldn't synthesize evsel unit.\n");
3702
- return err;
3703
- }
3704
- }
3705
-
3706
- if (has_scale(counter)) {
3707
- err = perf_event__synthesize_event_update_scale(tool, counter, process);
3708
- if (err < 0) {
3709
- pr_err("Couldn't synthesize evsel counter.\n");
3710
- return err;
3711
- }
3712
- }
3713
-
3714
- if (counter->own_cpus) {
3715
- err = perf_event__synthesize_event_update_cpus(tool, counter, process);
3716
- if (err < 0) {
3717
- pr_err("Couldn't synthesize evsel cpus.\n");
3718
- return err;
3719
- }
3720
- }
3721
-
3722
- /*
3723
- * Name is needed only for pipe output,
3724
- * perf.data carries event names.
3725
- */
3726
- if (is_pipe) {
3727
- err = perf_event__synthesize_event_update_name(tool, counter, process);
3728
- if (err < 0) {
3729
- pr_err("Couldn't synthesize evsel name.\n");
3730
- return err;
3731
- }
3732
- }
3733
- }
3734
- return 0;
3735
-}
3736
-
37373986 int perf_event__process_attr(struct perf_tool *tool __maybe_unused,
37383987 union perf_event *event,
3739
- struct perf_evlist **pevlist)
3988
+ struct evlist **pevlist)
37403989 {
37413990 u32 i, ids, n_ids;
3742
- struct perf_evsel *evsel;
3743
- struct perf_evlist *evlist = *pevlist;
3991
+ struct evsel *evsel;
3992
+ struct evlist *evlist = *pevlist;
37443993
37453994 if (evlist == NULL) {
3746
- *pevlist = evlist = perf_evlist__new();
3995
+ *pevlist = evlist = evlist__new();
37473996 if (evlist == NULL)
37483997 return -ENOMEM;
37493998 }
37503999
3751
- evsel = perf_evsel__new(&event->attr.attr);
4000
+ evsel = evsel__new(&event->attr.attr);
37524001 if (evsel == NULL)
37534002 return -ENOMEM;
37544003
3755
- perf_evlist__add(evlist, evsel);
4004
+ evlist__add(evlist, evsel);
37564005
37574006 ids = event->header.size;
37584007 ids -= (void *)&event->attr.id - (void *)event;
....@@ -3762,11 +4011,11 @@
37624011 * for allocating the perf_sample_id table we fake 1 cpu and
37634012 * hattr->ids threads.
37644013 */
3765
- if (perf_evsel__alloc_id(evsel, 1, n_ids))
4014
+ if (perf_evsel__alloc_id(&evsel->core, 1, n_ids))
37664015 return -ENOMEM;
37674016
37684017 for (i = 0; i < n_ids; i++) {
3769
- perf_evlist__id_add(evlist, evsel, 0, i, event->attr.id[i]);
4018
+ perf_evlist__id_add(&evlist->core, &evsel->core, 0, i, event->attr.id[i]);
37704019 }
37714020
37724021 return 0;
....@@ -3774,14 +4023,14 @@
37744023
37754024 int perf_event__process_event_update(struct perf_tool *tool __maybe_unused,
37764025 union perf_event *event,
3777
- struct perf_evlist **pevlist)
4026
+ struct evlist **pevlist)
37784027 {
3779
- struct event_update_event *ev = &event->event_update;
3780
- struct event_update_event_scale *ev_scale;
3781
- struct event_update_event_cpus *ev_cpus;
3782
- struct perf_evlist *evlist;
3783
- struct perf_evsel *evsel;
3784
- struct cpu_map *map;
4028
+ struct perf_record_event_update *ev = &event->event_update;
4029
+ struct perf_record_event_update_scale *ev_scale;
4030
+ struct perf_record_event_update_cpus *ev_cpus;
4031
+ struct evlist *evlist;
4032
+ struct evsel *evsel;
4033
+ struct perf_cpu_map *map;
37854034
37864035 if (!pevlist || *pevlist == NULL)
37874036 return -EINVAL;
....@@ -3800,15 +4049,15 @@
38004049 evsel->name = strdup(ev->data);
38014050 break;
38024051 case PERF_EVENT_UPDATE__SCALE:
3803
- ev_scale = (struct event_update_event_scale *) ev->data;
4052
+ ev_scale = (struct perf_record_event_update_scale *)ev->data;
38044053 evsel->scale = ev_scale->scale;
38054054 break;
38064055 case PERF_EVENT_UPDATE__CPUS:
3807
- ev_cpus = (struct event_update_event_cpus *) ev->data;
4056
+ ev_cpus = (struct perf_record_event_update_cpus *)ev->data;
38084057
38094058 map = cpu_map__new_data(&ev_cpus->cpus);
38104059 if (map)
3811
- evsel->own_cpus = map;
4060
+ evsel->core.own_cpus = map;
38124061 else
38134062 pr_err("failed to get event_update cpus\n");
38144063 default:
....@@ -3818,67 +4067,27 @@
38184067 return 0;
38194068 }
38204069
3821
-int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd,
3822
- struct perf_evlist *evlist,
3823
- perf_event__handler_t process)
3824
-{
3825
- union perf_event ev;
3826
- struct tracing_data *tdata;
3827
- ssize_t size = 0, aligned_size = 0, padding;
3828
- struct feat_fd ff;
3829
- int err __maybe_unused = 0;
3830
-
3831
- /*
3832
- * We are going to store the size of the data followed
3833
- * by the data contents. Since the fd descriptor is a pipe,
3834
- * we cannot seek back to store the size of the data once
3835
- * we know it. Instead we:
3836
- *
3837
- * - write the tracing data to the temp file
3838
- * - get/write the data size to pipe
3839
- * - write the tracing data from the temp file
3840
- * to the pipe
3841
- */
3842
- tdata = tracing_data_get(&evlist->entries, fd, true);
3843
- if (!tdata)
3844
- return -1;
3845
-
3846
- memset(&ev, 0, sizeof(ev));
3847
-
3848
- ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA;
3849
- size = tdata->size;
3850
- aligned_size = PERF_ALIGN(size, sizeof(u64));
3851
- padding = aligned_size - size;
3852
- ev.tracing_data.header.size = sizeof(ev.tracing_data);
3853
- ev.tracing_data.size = aligned_size;
3854
-
3855
- process(tool, &ev, NULL, NULL);
3856
-
3857
- /*
3858
- * The put function will copy all the tracing data
3859
- * stored in temp file to the pipe.
3860
- */
3861
- tracing_data_put(tdata);
3862
-
3863
- ff = (struct feat_fd){ .fd = fd };
3864
- if (write_padded(&ff, NULL, 0, padding))
3865
- return -1;
3866
-
3867
- return aligned_size;
3868
-}
3869
-
3870
-int perf_event__process_tracing_data(struct perf_tool *tool __maybe_unused,
3871
- union perf_event *event,
3872
- struct perf_session *session)
4070
+int perf_event__process_tracing_data(struct perf_session *session,
4071
+ union perf_event *event)
38734072 {
38744073 ssize_t size_read, padding, size = event->tracing_data.size;
38754074 int fd = perf_data__fd(session->data);
3876
- off_t offset = lseek(fd, 0, SEEK_CUR);
38774075 char buf[BUFSIZ];
38784076
3879
- /* setup for reading amidst mmap */
3880
- lseek(fd, offset + sizeof(struct tracing_data_event),
3881
- SEEK_SET);
4077
+ /*
4078
+ * The pipe fd is already in proper place and in any case
4079
+ * we can't move it, and we'd screw the case where we read
4080
+ * 'pipe' data from regular file. The trace_report reads
4081
+ * data from 'fd' so we need to set it directly behind the
4082
+ * event, where the tracing data starts.
4083
+ */
4084
+ if (!perf_data__is_pipe(session->data)) {
4085
+ off_t offset = lseek(fd, 0, SEEK_CUR);
4086
+
4087
+ /* setup for reading amidst mmap */
4088
+ lseek(fd, offset + sizeof(struct perf_record_header_tracing_data),
4089
+ SEEK_SET);
4090
+ }
38824091
38834092 size_read = trace_report(fd, &session->tevent,
38844093 session->repipe);
....@@ -3907,37 +4116,8 @@
39074116 return size_read + padding;
39084117 }
39094118
3910
-int perf_event__synthesize_build_id(struct perf_tool *tool,
3911
- struct dso *pos, u16 misc,
3912
- perf_event__handler_t process,
3913
- struct machine *machine)
3914
-{
3915
- union perf_event ev;
3916
- size_t len;
3917
- int err = 0;
3918
-
3919
- if (!pos->hit)
3920
- return err;
3921
-
3922
- memset(&ev, 0, sizeof(ev));
3923
-
3924
- len = pos->long_name_len + 1;
3925
- len = PERF_ALIGN(len, NAME_ALIGN);
3926
- memcpy(&ev.build_id.build_id, pos->build_id, sizeof(pos->build_id));
3927
- ev.build_id.header.type = PERF_RECORD_HEADER_BUILD_ID;
3928
- ev.build_id.header.misc = misc;
3929
- ev.build_id.pid = machine->pid;
3930
- ev.build_id.header.size = sizeof(ev.build_id) + len;
3931
- memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len);
3932
-
3933
- err = process(tool, &ev, NULL, machine);
3934
-
3935
- return err;
3936
-}
3937
-
3938
-int perf_event__process_build_id(struct perf_tool *tool __maybe_unused,
3939
- union perf_event *event,
3940
- struct perf_session *session)
4119
+int perf_event__process_build_id(struct perf_session *session,
4120
+ union perf_event *event)
39414121 {
39424122 __event_process_build_id(&event->build_id,
39434123 event->build_id.filename,