diff options
author | Ingo Molnar <mingo@kernel.org> | 2012-09-24 14:55:26 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2012-09-24 14:55:26 -0400 |
commit | f74eb728687afbf239abe2ea66921583db4eaa4b (patch) | |
tree | 47705ee82ead642e9a4b71edb39988c4b991a4ec /tools/perf/util | |
parent | 50a011f6409e888d5f41343024d24885281f048c (diff) | |
parent | b1ac754b67b5a875d63bee880f60ccb0c6bd8899 (diff) |
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:
* Convert the trace builtins to use the growing evsel/evlist
tracepoint infrastructure, removing several open coded constructs
like switch like series of strcmp to dispatch events, etc.
Basically what had already been showcased in 'perf sched'.
* Add evsel constructor for tracepoints, that uses libtraceevent
just to parse the /format events file, use it in a new 'perf test'
to make sure the libtraceevent format parsing regressions can
be more readily caught.
* Some strange errors were happening in some builds, but not on the
next, reported by several people, problem was some parser related
files, generated during the build, didn't had proper make deps,
fix from Eric Sandeen.
* Fix some compiling errors on 32-bit, from Feng Tang.
* Don't use sscanf extension %as, not available on bionic, reimplementation
by Irina Tirdea.
* Fix bfd.h/libbfd detection with recent binutils, from Markus Trippelsdorf.
* Introduce struct and cache information about the environment where a
perf.data file was captured, from Namhyung Kim.
* Fix several error paths in libtraceevent, from Namhyung Kim.
Print event causing perf_event_open() to fail in 'perf record',
from Stephane Eranian.
* New 'kvm' analysis tool, from Xiao Guangrong.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util')
-rw-r--r-- | tools/perf/util/evsel.c | 88 | ||||
-rw-r--r-- | tools/perf/util/evsel.h | 5 | ||||
-rw-r--r-- | tools/perf/util/header.c | 547 | ||||
-rw-r--r-- | tools/perf/util/header.h | 24 | ||||
-rw-r--r-- | tools/perf/util/map.c | 5 | ||||
-rw-r--r-- | tools/perf/util/probe-event.c | 36 | ||||
-rw-r--r-- | tools/perf/util/scripting-engines/trace-event-perl.c | 2 | ||||
-rw-r--r-- | tools/perf/util/symbol.h | 1 | ||||
-rw-r--r-- | tools/perf/util/thread.h | 2 | ||||
-rw-r--r-- | tools/perf/util/trace-event-parse.c | 18 |
10 files changed, 538 insertions, 190 deletions
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 1506ba0453f1..00936ad29ff2 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <byteswap.h> | 10 | #include <byteswap.h> |
11 | #include <linux/bitops.h> | 11 | #include <linux/bitops.h> |
12 | #include "asm/bug.h" | 12 | #include "asm/bug.h" |
13 | #include "debugfs.h" | ||
13 | #include "event-parse.h" | 14 | #include "event-parse.h" |
14 | #include "evsel.h" | 15 | #include "evsel.h" |
15 | #include "evlist.h" | 16 | #include "evlist.h" |
@@ -69,6 +70,72 @@ struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx) | |||
69 | return evsel; | 70 | return evsel; |
70 | } | 71 | } |
71 | 72 | ||
73 | static struct event_format *event_format__new(const char *sys, const char *name) | ||
74 | { | ||
75 | int fd, n; | ||
76 | char *filename; | ||
77 | void *bf = NULL, *nbf; | ||
78 | size_t size = 0, alloc_size = 0; | ||
79 | struct event_format *format = NULL; | ||
80 | |||
81 | if (asprintf(&filename, "%s/%s/%s/format", tracing_events_path, sys, name) < 0) | ||
82 | goto out; | ||
83 | |||
84 | fd = open(filename, O_RDONLY); | ||
85 | if (fd < 0) | ||
86 | goto out_free_filename; | ||
87 | |||
88 | do { | ||
89 | if (size == alloc_size) { | ||
90 | alloc_size += BUFSIZ; | ||
91 | nbf = realloc(bf, alloc_size); | ||
92 | if (nbf == NULL) | ||
93 | goto out_free_bf; | ||
94 | bf = nbf; | ||
95 | } | ||
96 | |||
97 | n = read(fd, bf + size, BUFSIZ); | ||
98 | if (n < 0) | ||
99 | goto out_free_bf; | ||
100 | size += n; | ||
101 | } while (n > 0); | ||
102 | |||
103 | pevent_parse_format(&format, bf, size, sys); | ||
104 | |||
105 | out_free_bf: | ||
106 | free(bf); | ||
107 | close(fd); | ||
108 | out_free_filename: | ||
109 | free(filename); | ||
110 | out: | ||
111 | return format; | ||
112 | } | ||
113 | |||
114 | struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name, int idx) | ||
115 | { | ||
116 | struct perf_evsel *evsel = zalloc(sizeof(*evsel)); | ||
117 | |||
118 | if (evsel != NULL) { | ||
119 | struct perf_event_attr attr = { | ||
120 | .type = PERF_TYPE_TRACEPOINT, | ||
121 | }; | ||
122 | |||
123 | evsel->tp_format = event_format__new(sys, name); | ||
124 | if (evsel->tp_format == NULL) | ||
125 | goto out_free; | ||
126 | |||
127 | attr.config = evsel->tp_format->id; | ||
128 | perf_evsel__init(evsel, &attr, idx); | ||
129 | evsel->name = evsel->tp_format->name; | ||
130 | } | ||
131 | |||
132 | return evsel; | ||
133 | |||
134 | out_free: | ||
135 | free(evsel); | ||
136 | return NULL; | ||
137 | } | ||
138 | |||
72 | const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = { | 139 | const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = { |
73 | "cycles", | 140 | "cycles", |
74 | "instructions", | 141 | "instructions", |
@@ -495,6 +562,10 @@ void perf_evsel__delete(struct perf_evsel *evsel) | |||
495 | perf_evsel__exit(evsel); | 562 | perf_evsel__exit(evsel); |
496 | close_cgroup(evsel->cgrp); | 563 | close_cgroup(evsel->cgrp); |
497 | free(evsel->group_name); | 564 | free(evsel->group_name); |
565 | if (evsel->tp_format && evsel->name == evsel->tp_format->name) { | ||
566 | evsel->name = NULL; | ||
567 | pevent_free_format(evsel->tp_format); | ||
568 | } | ||
498 | free(evsel->name); | 569 | free(evsel->name); |
499 | free(evsel); | 570 | free(evsel); |
500 | } | 571 | } |
@@ -1002,14 +1073,19 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type, | |||
1002 | return 0; | 1073 | return 0; |
1003 | } | 1074 | } |
1004 | 1075 | ||
1076 | struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name) | ||
1077 | { | ||
1078 | return pevent_find_field(evsel->tp_format, name); | ||
1079 | } | ||
1080 | |||
1005 | char *perf_evsel__strval(struct perf_evsel *evsel, struct perf_sample *sample, | 1081 | char *perf_evsel__strval(struct perf_evsel *evsel, struct perf_sample *sample, |
1006 | const char *name) | 1082 | const char *name) |
1007 | { | 1083 | { |
1008 | struct format_field *field = pevent_find_field(evsel->tp_format, name); | 1084 | struct format_field *field = perf_evsel__field(evsel, name); |
1009 | int offset; | 1085 | int offset; |
1010 | 1086 | ||
1011 | if (!field) | 1087 | if (!field) |
1012 | return NULL; | 1088 | return NULL; |
1013 | 1089 | ||
1014 | offset = field->offset; | 1090 | offset = field->offset; |
1015 | 1091 | ||
@@ -1024,11 +1100,11 @@ char *perf_evsel__strval(struct perf_evsel *evsel, struct perf_sample *sample, | |||
1024 | u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, | 1100 | u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, |
1025 | const char *name) | 1101 | const char *name) |
1026 | { | 1102 | { |
1027 | struct format_field *field = pevent_find_field(evsel->tp_format, name); | 1103 | struct format_field *field = perf_evsel__field(evsel, name); |
1028 | u64 val; | 1104 | u64 val; |
1029 | 1105 | ||
1030 | if (!field) | 1106 | if (!field) |
1031 | return 0; | 1107 | return 0; |
1032 | 1108 | ||
1033 | val = pevent_read_number(evsel->tp_format->pevent, | 1109 | val = pevent_read_number(evsel->tp_format->pevent, |
1034 | sample->raw_data + field->offset, field->size); | 1110 | sample->raw_data + field->offset, field->size); |
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 93876bad2e52..bb445d1cbc7b 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h | |||
@@ -81,6 +81,7 @@ struct perf_evlist; | |||
81 | struct perf_record_opts; | 81 | struct perf_record_opts; |
82 | 82 | ||
83 | struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx); | 83 | struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx); |
84 | struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name, int idx); | ||
84 | void perf_evsel__init(struct perf_evsel *evsel, | 85 | void perf_evsel__init(struct perf_evsel *evsel, |
85 | struct perf_event_attr *attr, int idx); | 86 | struct perf_event_attr *attr, int idx); |
86 | void perf_evsel__exit(struct perf_evsel *evsel); | 87 | void perf_evsel__exit(struct perf_evsel *evsel); |
@@ -128,6 +129,10 @@ char *perf_evsel__strval(struct perf_evsel *evsel, struct perf_sample *sample, | |||
128 | u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, | 129 | u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, |
129 | const char *name); | 130 | const char *name); |
130 | 131 | ||
132 | struct format_field; | ||
133 | |||
134 | struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name); | ||
135 | |||
131 | #define perf_evsel__match(evsel, t, c) \ | 136 | #define perf_evsel__match(evsel, t, c) \ |
132 | (evsel->attr.type == PERF_TYPE_##t && \ | 137 | (evsel->attr.type == PERF_TYPE_##t && \ |
133 | evsel->attr.config == PERF_COUNT_##c) | 138 | evsel->attr.config == PERF_COUNT_##c) |
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index acbf6336199e..6aae3290358e 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include "cpumap.h" | 22 | #include "cpumap.h" |
23 | #include "pmu.h" | 23 | #include "pmu.h" |
24 | #include "vdso.h" | 24 | #include "vdso.h" |
25 | #include "strbuf.h" | ||
25 | 26 | ||
26 | static bool no_buildid_cache = false; | 27 | static bool no_buildid_cache = false; |
27 | 28 | ||
@@ -1102,118 +1103,80 @@ static int write_branch_stack(int fd __maybe_unused, | |||
1102 | return 0; | 1103 | return 0; |
1103 | } | 1104 | } |
1104 | 1105 | ||
1105 | static void print_hostname(struct perf_header *ph, int fd, FILE *fp) | 1106 | static void print_hostname(struct perf_header *ph, int fd __maybe_unused, |
1107 | FILE *fp) | ||
1106 | { | 1108 | { |
1107 | char *str = do_read_string(fd, ph); | 1109 | fprintf(fp, "# hostname : %s\n", ph->env.hostname); |
1108 | fprintf(fp, "# hostname : %s\n", str); | ||
1109 | free(str); | ||
1110 | } | 1110 | } |
1111 | 1111 | ||
1112 | static void print_osrelease(struct perf_header *ph, int fd, FILE *fp) | 1112 | static void print_osrelease(struct perf_header *ph, int fd __maybe_unused, |
1113 | FILE *fp) | ||
1113 | { | 1114 | { |
1114 | char *str = do_read_string(fd, ph); | 1115 | fprintf(fp, "# os release : %s\n", ph->env.os_release); |
1115 | fprintf(fp, "# os release : %s\n", str); | ||
1116 | free(str); | ||
1117 | } | 1116 | } |
1118 | 1117 | ||
1119 | static void print_arch(struct perf_header *ph, int fd, FILE *fp) | 1118 | static void print_arch(struct perf_header *ph, int fd __maybe_unused, FILE *fp) |
1120 | { | 1119 | { |
1121 | char *str = do_read_string(fd, ph); | 1120 | fprintf(fp, "# arch : %s\n", ph->env.arch); |
1122 | fprintf(fp, "# arch : %s\n", str); | ||
1123 | free(str); | ||
1124 | } | 1121 | } |
1125 | 1122 | ||
1126 | static void print_cpudesc(struct perf_header *ph, int fd, FILE *fp) | 1123 | static void print_cpudesc(struct perf_header *ph, int fd __maybe_unused, |
1124 | FILE *fp) | ||
1127 | { | 1125 | { |
1128 | char *str = do_read_string(fd, ph); | 1126 | fprintf(fp, "# cpudesc : %s\n", ph->env.cpu_desc); |
1129 | fprintf(fp, "# cpudesc : %s\n", str); | ||
1130 | free(str); | ||
1131 | } | 1127 | } |
1132 | 1128 | ||
1133 | static void print_nrcpus(struct perf_header *ph, int fd, FILE *fp) | 1129 | static void print_nrcpus(struct perf_header *ph, int fd __maybe_unused, |
1130 | FILE *fp) | ||
1134 | { | 1131 | { |
1135 | ssize_t ret; | 1132 | fprintf(fp, "# nrcpus online : %u\n", ph->env.nr_cpus_online); |
1136 | u32 nr; | 1133 | fprintf(fp, "# nrcpus avail : %u\n", ph->env.nr_cpus_avail); |
1137 | |||
1138 | ret = read(fd, &nr, sizeof(nr)); | ||
1139 | if (ret != (ssize_t)sizeof(nr)) | ||
1140 | nr = -1; /* interpreted as error */ | ||
1141 | |||
1142 | if (ph->needs_swap) | ||
1143 | nr = bswap_32(nr); | ||
1144 | |||
1145 | fprintf(fp, "# nrcpus online : %u\n", nr); | ||
1146 | |||
1147 | ret = read(fd, &nr, sizeof(nr)); | ||
1148 | if (ret != (ssize_t)sizeof(nr)) | ||
1149 | nr = -1; /* interpreted as error */ | ||
1150 | |||
1151 | if (ph->needs_swap) | ||
1152 | nr = bswap_32(nr); | ||
1153 | |||
1154 | fprintf(fp, "# nrcpus avail : %u\n", nr); | ||
1155 | } | 1134 | } |
1156 | 1135 | ||
1157 | static void print_version(struct perf_header *ph, int fd, FILE *fp) | 1136 | static void print_version(struct perf_header *ph, int fd __maybe_unused, |
1137 | FILE *fp) | ||
1158 | { | 1138 | { |
1159 | char *str = do_read_string(fd, ph); | 1139 | fprintf(fp, "# perf version : %s\n", ph->env.version); |
1160 | fprintf(fp, "# perf version : %s\n", str); | ||
1161 | free(str); | ||
1162 | } | 1140 | } |
1163 | 1141 | ||
1164 | static void print_cmdline(struct perf_header *ph, int fd, FILE *fp) | 1142 | static void print_cmdline(struct perf_header *ph, int fd __maybe_unused, |
1143 | FILE *fp) | ||
1165 | { | 1144 | { |
1166 | ssize_t ret; | 1145 | int nr, i; |
1167 | char *str; | 1146 | char *str; |
1168 | u32 nr, i; | ||
1169 | |||
1170 | ret = read(fd, &nr, sizeof(nr)); | ||
1171 | if (ret != (ssize_t)sizeof(nr)) | ||
1172 | return; | ||
1173 | 1147 | ||
1174 | if (ph->needs_swap) | 1148 | nr = ph->env.nr_cmdline; |
1175 | nr = bswap_32(nr); | 1149 | str = ph->env.cmdline; |
1176 | 1150 | ||
1177 | fprintf(fp, "# cmdline : "); | 1151 | fprintf(fp, "# cmdline : "); |
1178 | 1152 | ||
1179 | for (i = 0; i < nr; i++) { | 1153 | for (i = 0; i < nr; i++) { |
1180 | str = do_read_string(fd, ph); | ||
1181 | fprintf(fp, "%s ", str); | 1154 | fprintf(fp, "%s ", str); |
1182 | free(str); | 1155 | str += strlen(str) + 1; |
1183 | } | 1156 | } |
1184 | fputc('\n', fp); | 1157 | fputc('\n', fp); |
1185 | } | 1158 | } |
1186 | 1159 | ||
1187 | static void print_cpu_topology(struct perf_header *ph, int fd, FILE *fp) | 1160 | static void print_cpu_topology(struct perf_header *ph, int fd __maybe_unused, |
1161 | FILE *fp) | ||
1188 | { | 1162 | { |
1189 | ssize_t ret; | 1163 | int nr, i; |
1190 | u32 nr, i; | ||
1191 | char *str; | 1164 | char *str; |
1192 | 1165 | ||
1193 | ret = read(fd, &nr, sizeof(nr)); | 1166 | nr = ph->env.nr_sibling_cores; |
1194 | if (ret != (ssize_t)sizeof(nr)) | 1167 | str = ph->env.sibling_cores; |
1195 | return; | ||
1196 | |||
1197 | if (ph->needs_swap) | ||
1198 | nr = bswap_32(nr); | ||
1199 | 1168 | ||
1200 | for (i = 0; i < nr; i++) { | 1169 | for (i = 0; i < nr; i++) { |
1201 | str = do_read_string(fd, ph); | ||
1202 | fprintf(fp, "# sibling cores : %s\n", str); | 1170 | fprintf(fp, "# sibling cores : %s\n", str); |
1203 | free(str); | 1171 | str += strlen(str) + 1; |
1204 | } | 1172 | } |
1205 | 1173 | ||
1206 | ret = read(fd, &nr, sizeof(nr)); | 1174 | nr = ph->env.nr_sibling_threads; |
1207 | if (ret != (ssize_t)sizeof(nr)) | 1175 | str = ph->env.sibling_threads; |
1208 | return; | ||
1209 | |||
1210 | if (ph->needs_swap) | ||
1211 | nr = bswap_32(nr); | ||
1212 | 1176 | ||
1213 | for (i = 0; i < nr; i++) { | 1177 | for (i = 0; i < nr; i++) { |
1214 | str = do_read_string(fd, ph); | ||
1215 | fprintf(fp, "# sibling threads : %s\n", str); | 1178 | fprintf(fp, "# sibling threads : %s\n", str); |
1216 | free(str); | 1179 | str += strlen(str) + 1; |
1217 | } | 1180 | } |
1218 | } | 1181 | } |
1219 | 1182 | ||
@@ -1374,126 +1337,89 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp) | |||
1374 | free_event_desc(events); | 1337 | free_event_desc(events); |
1375 | } | 1338 | } |
1376 | 1339 | ||
1377 | static void print_total_mem(struct perf_header *h __maybe_unused, int fd, | 1340 | static void print_total_mem(struct perf_header *ph, int fd __maybe_unused, |
1378 | FILE *fp) | 1341 | FILE *fp) |
1379 | { | 1342 | { |
1380 | uint64_t mem; | 1343 | fprintf(fp, "# total memory : %Lu kB\n", ph->env.total_mem); |
1381 | ssize_t ret; | ||
1382 | |||
1383 | ret = read(fd, &mem, sizeof(mem)); | ||
1384 | if (ret != sizeof(mem)) | ||
1385 | goto error; | ||
1386 | |||
1387 | if (h->needs_swap) | ||
1388 | mem = bswap_64(mem); | ||
1389 | |||
1390 | fprintf(fp, "# total memory : %"PRIu64" kB\n", mem); | ||
1391 | return; | ||
1392 | error: | ||
1393 | fprintf(fp, "# total memory : unknown\n"); | ||
1394 | } | 1344 | } |
1395 | 1345 | ||
1396 | static void print_numa_topology(struct perf_header *h __maybe_unused, int fd, | 1346 | static void print_numa_topology(struct perf_header *ph, int fd __maybe_unused, |
1397 | FILE *fp) | 1347 | FILE *fp) |
1398 | { | 1348 | { |
1399 | ssize_t ret; | ||
1400 | u32 nr, c, i; | 1349 | u32 nr, c, i; |
1401 | char *str; | 1350 | char *str, *tmp; |
1402 | uint64_t mem_total, mem_free; | 1351 | uint64_t mem_total, mem_free; |
1403 | 1352 | ||
1404 | /* nr nodes */ | 1353 | /* nr nodes */ |
1405 | ret = read(fd, &nr, sizeof(nr)); | 1354 | nr = ph->env.nr_numa_nodes; |
1406 | if (ret != (ssize_t)sizeof(nr)) | 1355 | str = ph->env.numa_nodes; |
1407 | goto error; | ||
1408 | |||
1409 | if (h->needs_swap) | ||
1410 | nr = bswap_32(nr); | ||
1411 | 1356 | ||
1412 | for (i = 0; i < nr; i++) { | 1357 | for (i = 0; i < nr; i++) { |
1413 | |||
1414 | /* node number */ | 1358 | /* node number */ |
1415 | ret = read(fd, &c, sizeof(c)); | 1359 | c = strtoul(str, &tmp, 0); |
1416 | if (ret != (ssize_t)sizeof(c)) | 1360 | if (*tmp != ':') |
1417 | goto error; | 1361 | goto error; |
1418 | 1362 | ||
1419 | if (h->needs_swap) | 1363 | str = tmp + 1; |
1420 | c = bswap_32(c); | 1364 | mem_total = strtoull(str, &tmp, 0); |
1421 | 1365 | if (*tmp != ':') | |
1422 | ret = read(fd, &mem_total, sizeof(u64)); | ||
1423 | if (ret != sizeof(u64)) | ||
1424 | goto error; | 1366 | goto error; |
1425 | 1367 | ||
1426 | ret = read(fd, &mem_free, sizeof(u64)); | 1368 | str = tmp + 1; |
1427 | if (ret != sizeof(u64)) | 1369 | mem_free = strtoull(str, &tmp, 0); |
1370 | if (*tmp != ':') | ||
1428 | goto error; | 1371 | goto error; |
1429 | 1372 | ||
1430 | if (h->needs_swap) { | ||
1431 | mem_total = bswap_64(mem_total); | ||
1432 | mem_free = bswap_64(mem_free); | ||
1433 | } | ||
1434 | |||
1435 | fprintf(fp, "# node%u meminfo : total = %"PRIu64" kB," | 1373 | fprintf(fp, "# node%u meminfo : total = %"PRIu64" kB," |
1436 | " free = %"PRIu64" kB\n", | 1374 | " free = %"PRIu64" kB\n", |
1437 | c, | 1375 | c, mem_total, mem_free); |
1438 | mem_total, | ||
1439 | mem_free); | ||
1440 | 1376 | ||
1441 | str = do_read_string(fd, h); | 1377 | str = tmp + 1; |
1442 | fprintf(fp, "# node%u cpu list : %s\n", c, str); | 1378 | fprintf(fp, "# node%u cpu list : %s\n", c, str); |
1443 | free(str); | ||
1444 | } | 1379 | } |
1445 | return; | 1380 | return; |
1446 | error: | 1381 | error: |
1447 | fprintf(fp, "# numa topology : not available\n"); | 1382 | fprintf(fp, "# numa topology : not available\n"); |
1448 | } | 1383 | } |
1449 | 1384 | ||
1450 | static void print_cpuid(struct perf_header *ph, int fd, FILE *fp) | 1385 | static void print_cpuid(struct perf_header *ph, int fd __maybe_unused, FILE *fp) |
1451 | { | 1386 | { |
1452 | char *str = do_read_string(fd, ph); | 1387 | fprintf(fp, "# cpuid : %s\n", ph->env.cpuid); |
1453 | fprintf(fp, "# cpuid : %s\n", str); | ||
1454 | free(str); | ||
1455 | } | 1388 | } |
1456 | 1389 | ||
1457 | static void print_branch_stack(struct perf_header *ph __maybe_unused, | 1390 | static void print_branch_stack(struct perf_header *ph __maybe_unused, |
1458 | int fd __maybe_unused, | 1391 | int fd __maybe_unused, FILE *fp) |
1459 | FILE *fp) | ||
1460 | { | 1392 | { |
1461 | fprintf(fp, "# contains samples with branch stack\n"); | 1393 | fprintf(fp, "# contains samples with branch stack\n"); |
1462 | } | 1394 | } |
1463 | 1395 | ||
1464 | static void print_pmu_mappings(struct perf_header *ph, int fd, FILE *fp) | 1396 | static void print_pmu_mappings(struct perf_header *ph, int fd __maybe_unused, |
1397 | FILE *fp) | ||
1465 | { | 1398 | { |
1466 | const char *delimiter = "# pmu mappings: "; | 1399 | const char *delimiter = "# pmu mappings: "; |
1467 | char *name; | 1400 | char *str, *tmp; |
1468 | int ret; | ||
1469 | u32 pmu_num; | 1401 | u32 pmu_num; |
1470 | u32 type; | 1402 | u32 type; |
1471 | 1403 | ||
1472 | ret = read(fd, &pmu_num, sizeof(pmu_num)); | 1404 | pmu_num = ph->env.nr_pmu_mappings; |
1473 | if (ret != sizeof(pmu_num)) | ||
1474 | goto error; | ||
1475 | |||
1476 | if (ph->needs_swap) | ||
1477 | pmu_num = bswap_32(pmu_num); | ||
1478 | |||
1479 | if (!pmu_num) { | 1405 | if (!pmu_num) { |
1480 | fprintf(fp, "# pmu mappings: not available\n"); | 1406 | fprintf(fp, "# pmu mappings: not available\n"); |
1481 | return; | 1407 | return; |
1482 | } | 1408 | } |
1483 | 1409 | ||
1410 | str = ph->env.pmu_mappings; | ||
1411 | |||
1484 | while (pmu_num) { | 1412 | while (pmu_num) { |
1485 | if (read(fd, &type, sizeof(type)) != sizeof(type)) | 1413 | type = strtoul(str, &tmp, 0); |
1486 | break; | 1414 | if (*tmp != ':') |
1487 | if (ph->needs_swap) | 1415 | goto error; |
1488 | type = bswap_32(type); | 1416 | |
1417 | str = tmp + 1; | ||
1418 | fprintf(fp, "%s%s = %" PRIu32, delimiter, str, type); | ||
1489 | 1419 | ||
1490 | name = do_read_string(fd, ph); | ||
1491 | if (!name) | ||
1492 | break; | ||
1493 | pmu_num--; | ||
1494 | fprintf(fp, "%s%s = %" PRIu32, delimiter, name, type); | ||
1495 | free(name); | ||
1496 | delimiter = ", "; | 1420 | delimiter = ", "; |
1421 | str += strlen(str) + 1; | ||
1422 | pmu_num--; | ||
1497 | } | 1423 | } |
1498 | 1424 | ||
1499 | fprintf(fp, "\n"); | 1425 | fprintf(fp, "\n"); |
@@ -1654,18 +1580,16 @@ out: | |||
1654 | return err; | 1580 | return err; |
1655 | } | 1581 | } |
1656 | 1582 | ||
1657 | static int process_tracing_data(struct perf_file_section *section | 1583 | static int process_tracing_data(struct perf_file_section *section __maybe_unused, |
1658 | __maybe_unused, | 1584 | struct perf_header *ph __maybe_unused, |
1659 | struct perf_header *ph __maybe_unused, | 1585 | int fd, void *data) |
1660 | int feat __maybe_unused, int fd, void *data) | ||
1661 | { | 1586 | { |
1662 | trace_report(fd, data, false); | 1587 | trace_report(fd, data, false); |
1663 | return 0; | 1588 | return 0; |
1664 | } | 1589 | } |
1665 | 1590 | ||
1666 | static int process_build_id(struct perf_file_section *section, | 1591 | static int process_build_id(struct perf_file_section *section, |
1667 | struct perf_header *ph, | 1592 | struct perf_header *ph, int fd, |
1668 | int feat __maybe_unused, int fd, | ||
1669 | void *data __maybe_unused) | 1593 | void *data __maybe_unused) |
1670 | { | 1594 | { |
1671 | if (perf_header__read_build_ids(ph, fd, section->offset, section->size)) | 1595 | if (perf_header__read_build_ids(ph, fd, section->offset, section->size)) |
@@ -1673,6 +1597,99 @@ static int process_build_id(struct perf_file_section *section, | |||
1673 | return 0; | 1597 | return 0; |
1674 | } | 1598 | } |
1675 | 1599 | ||
1600 | static int process_hostname(struct perf_file_section *section __maybe_unused, | ||
1601 | struct perf_header *ph, int fd, | ||
1602 | void *data __maybe_unused) | ||
1603 | { | ||
1604 | ph->env.hostname = do_read_string(fd, ph); | ||
1605 | return ph->env.hostname ? 0 : -ENOMEM; | ||
1606 | } | ||
1607 | |||
1608 | static int process_osrelease(struct perf_file_section *section __maybe_unused, | ||
1609 | struct perf_header *ph, int fd, | ||
1610 | void *data __maybe_unused) | ||
1611 | { | ||
1612 | ph->env.os_release = do_read_string(fd, ph); | ||
1613 | return ph->env.os_release ? 0 : -ENOMEM; | ||
1614 | } | ||
1615 | |||
1616 | static int process_version(struct perf_file_section *section __maybe_unused, | ||
1617 | struct perf_header *ph, int fd, | ||
1618 | void *data __maybe_unused) | ||
1619 | { | ||
1620 | ph->env.version = do_read_string(fd, ph); | ||
1621 | return ph->env.version ? 0 : -ENOMEM; | ||
1622 | } | ||
1623 | |||
1624 | static int process_arch(struct perf_file_section *section __maybe_unused, | ||
1625 | struct perf_header *ph, int fd, | ||
1626 | void *data __maybe_unused) | ||
1627 | { | ||
1628 | ph->env.arch = do_read_string(fd, ph); | ||
1629 | return ph->env.arch ? 0 : -ENOMEM; | ||
1630 | } | ||
1631 | |||
1632 | static int process_nrcpus(struct perf_file_section *section __maybe_unused, | ||
1633 | struct perf_header *ph, int fd, | ||
1634 | void *data __maybe_unused) | ||
1635 | { | ||
1636 | size_t ret; | ||
1637 | u32 nr; | ||
1638 | |||
1639 | ret = read(fd, &nr, sizeof(nr)); | ||
1640 | if (ret != sizeof(nr)) | ||
1641 | return -1; | ||
1642 | |||
1643 | if (ph->needs_swap) | ||
1644 | nr = bswap_32(nr); | ||
1645 | |||
1646 | ph->env.nr_cpus_online = nr; | ||
1647 | |||
1648 | ret = read(fd, &nr, sizeof(nr)); | ||
1649 | if (ret != sizeof(nr)) | ||
1650 | return -1; | ||
1651 | |||
1652 | if (ph->needs_swap) | ||
1653 | nr = bswap_32(nr); | ||
1654 | |||
1655 | ph->env.nr_cpus_avail = nr; | ||
1656 | return 0; | ||
1657 | } | ||
1658 | |||
1659 | static int process_cpudesc(struct perf_file_section *section __maybe_unused, | ||
1660 | struct perf_header *ph, int fd, | ||
1661 | void *data __maybe_unused) | ||
1662 | { | ||
1663 | ph->env.cpu_desc = do_read_string(fd, ph); | ||
1664 | return ph->env.cpu_desc ? 0 : -ENOMEM; | ||
1665 | } | ||
1666 | |||
1667 | static int process_cpuid(struct perf_file_section *section __maybe_unused, | ||
1668 | struct perf_header *ph, int fd, | ||
1669 | void *data __maybe_unused) | ||
1670 | { | ||
1671 | ph->env.cpuid = do_read_string(fd, ph); | ||
1672 | return ph->env.cpuid ? 0 : -ENOMEM; | ||
1673 | } | ||
1674 | |||
1675 | static int process_total_mem(struct perf_file_section *section __maybe_unused, | ||
1676 | struct perf_header *ph, int fd, | ||
1677 | void *data __maybe_unused) | ||
1678 | { | ||
1679 | uint64_t mem; | ||
1680 | size_t ret; | ||
1681 | |||
1682 | ret = read(fd, &mem, sizeof(mem)); | ||
1683 | if (ret != sizeof(mem)) | ||
1684 | return -1; | ||
1685 | |||
1686 | if (ph->needs_swap) | ||
1687 | mem = bswap_64(mem); | ||
1688 | |||
1689 | ph->env.total_mem = mem; | ||
1690 | return 0; | ||
1691 | } | ||
1692 | |||
1676 | static struct perf_evsel * | 1693 | static struct perf_evsel * |
1677 | perf_evlist__find_by_index(struct perf_evlist *evlist, int idx) | 1694 | perf_evlist__find_by_index(struct perf_evlist *evlist, int idx) |
1678 | { | 1695 | { |
@@ -1687,7 +1704,8 @@ perf_evlist__find_by_index(struct perf_evlist *evlist, int idx) | |||
1687 | } | 1704 | } |
1688 | 1705 | ||
1689 | static void | 1706 | static void |
1690 | perf_evlist__set_event_name(struct perf_evlist *evlist, struct perf_evsel *event) | 1707 | perf_evlist__set_event_name(struct perf_evlist *evlist, |
1708 | struct perf_evsel *event) | ||
1691 | { | 1709 | { |
1692 | struct perf_evsel *evsel; | 1710 | struct perf_evsel *evsel; |
1693 | 1711 | ||
@@ -1706,15 +1724,16 @@ perf_evlist__set_event_name(struct perf_evlist *evlist, struct perf_evsel *event | |||
1706 | 1724 | ||
1707 | static int | 1725 | static int |
1708 | process_event_desc(struct perf_file_section *section __maybe_unused, | 1726 | process_event_desc(struct perf_file_section *section __maybe_unused, |
1709 | struct perf_header *header, int feat __maybe_unused, int fd, | 1727 | struct perf_header *header, int fd, |
1710 | void *data __maybe_unused) | 1728 | void *data __maybe_unused) |
1711 | { | 1729 | { |
1712 | struct perf_session *session = container_of(header, struct perf_session, header); | 1730 | struct perf_session *session; |
1713 | struct perf_evsel *evsel, *events = read_event_desc(header, fd); | 1731 | struct perf_evsel *evsel, *events = read_event_desc(header, fd); |
1714 | 1732 | ||
1715 | if (!events) | 1733 | if (!events) |
1716 | return 0; | 1734 | return 0; |
1717 | 1735 | ||
1736 | session = container_of(header, struct perf_session, header); | ||
1718 | for (evsel = events; evsel->attr.size; evsel++) | 1737 | for (evsel = events; evsel->attr.size; evsel++) |
1719 | perf_evlist__set_event_name(session->evlist, evsel); | 1738 | perf_evlist__set_event_name(session->evlist, evsel); |
1720 | 1739 | ||
@@ -1723,11 +1742,213 @@ process_event_desc(struct perf_file_section *section __maybe_unused, | |||
1723 | return 0; | 1742 | return 0; |
1724 | } | 1743 | } |
1725 | 1744 | ||
1745 | static int process_cmdline(struct perf_file_section *section __maybe_unused, | ||
1746 | struct perf_header *ph, int fd, | ||
1747 | void *data __maybe_unused) | ||
1748 | { | ||
1749 | size_t ret; | ||
1750 | char *str; | ||
1751 | u32 nr, i; | ||
1752 | struct strbuf sb; | ||
1753 | |||
1754 | ret = read(fd, &nr, sizeof(nr)); | ||
1755 | if (ret != sizeof(nr)) | ||
1756 | return -1; | ||
1757 | |||
1758 | if (ph->needs_swap) | ||
1759 | nr = bswap_32(nr); | ||
1760 | |||
1761 | ph->env.nr_cmdline = nr; | ||
1762 | strbuf_init(&sb, 128); | ||
1763 | |||
1764 | for (i = 0; i < nr; i++) { | ||
1765 | str = do_read_string(fd, ph); | ||
1766 | if (!str) | ||
1767 | goto error; | ||
1768 | |||
1769 | /* include a NULL character at the end */ | ||
1770 | strbuf_add(&sb, str, strlen(str) + 1); | ||
1771 | free(str); | ||
1772 | } | ||
1773 | ph->env.cmdline = strbuf_detach(&sb, NULL); | ||
1774 | return 0; | ||
1775 | |||
1776 | error: | ||
1777 | strbuf_release(&sb); | ||
1778 | return -1; | ||
1779 | } | ||
1780 | |||
1781 | static int process_cpu_topology(struct perf_file_section *section __maybe_unused, | ||
1782 | struct perf_header *ph, int fd, | ||
1783 | void *data __maybe_unused) | ||
1784 | { | ||
1785 | size_t ret; | ||
1786 | u32 nr, i; | ||
1787 | char *str; | ||
1788 | struct strbuf sb; | ||
1789 | |||
1790 | ret = read(fd, &nr, sizeof(nr)); | ||
1791 | if (ret != sizeof(nr)) | ||
1792 | return -1; | ||
1793 | |||
1794 | if (ph->needs_swap) | ||
1795 | nr = bswap_32(nr); | ||
1796 | |||
1797 | ph->env.nr_sibling_cores = nr; | ||
1798 | strbuf_init(&sb, 128); | ||
1799 | |||
1800 | for (i = 0; i < nr; i++) { | ||
1801 | str = do_read_string(fd, ph); | ||
1802 | if (!str) | ||
1803 | goto error; | ||
1804 | |||
1805 | /* include a NULL character at the end */ | ||
1806 | strbuf_add(&sb, str, strlen(str) + 1); | ||
1807 | free(str); | ||
1808 | } | ||
1809 | ph->env.sibling_cores = strbuf_detach(&sb, NULL); | ||
1810 | |||
1811 | ret = read(fd, &nr, sizeof(nr)); | ||
1812 | if (ret != sizeof(nr)) | ||
1813 | return -1; | ||
1814 | |||
1815 | if (ph->needs_swap) | ||
1816 | nr = bswap_32(nr); | ||
1817 | |||
1818 | ph->env.nr_sibling_threads = nr; | ||
1819 | |||
1820 | for (i = 0; i < nr; i++) { | ||
1821 | str = do_read_string(fd, ph); | ||
1822 | if (!str) | ||
1823 | goto error; | ||
1824 | |||
1825 | /* include a NULL character at the end */ | ||
1826 | strbuf_add(&sb, str, strlen(str) + 1); | ||
1827 | free(str); | ||
1828 | } | ||
1829 | ph->env.sibling_threads = strbuf_detach(&sb, NULL); | ||
1830 | return 0; | ||
1831 | |||
1832 | error: | ||
1833 | strbuf_release(&sb); | ||
1834 | return -1; | ||
1835 | } | ||
1836 | |||
1837 | static int process_numa_topology(struct perf_file_section *section __maybe_unused, | ||
1838 | struct perf_header *ph, int fd, | ||
1839 | void *data __maybe_unused) | ||
1840 | { | ||
1841 | size_t ret; | ||
1842 | u32 nr, node, i; | ||
1843 | char *str; | ||
1844 | uint64_t mem_total, mem_free; | ||
1845 | struct strbuf sb; | ||
1846 | |||
1847 | /* nr nodes */ | ||
1848 | ret = read(fd, &nr, sizeof(nr)); | ||
1849 | if (ret != sizeof(nr)) | ||
1850 | goto error; | ||
1851 | |||
1852 | if (ph->needs_swap) | ||
1853 | nr = bswap_32(nr); | ||
1854 | |||
1855 | ph->env.nr_numa_nodes = nr; | ||
1856 | strbuf_init(&sb, 256); | ||
1857 | |||
1858 | for (i = 0; i < nr; i++) { | ||
1859 | /* node number */ | ||
1860 | ret = read(fd, &node, sizeof(node)); | ||
1861 | if (ret != sizeof(node)) | ||
1862 | goto error; | ||
1863 | |||
1864 | ret = read(fd, &mem_total, sizeof(u64)); | ||
1865 | if (ret != sizeof(u64)) | ||
1866 | goto error; | ||
1867 | |||
1868 | ret = read(fd, &mem_free, sizeof(u64)); | ||
1869 | if (ret != sizeof(u64)) | ||
1870 | goto error; | ||
1871 | |||
1872 | if (ph->needs_swap) { | ||
1873 | node = bswap_32(node); | ||
1874 | mem_total = bswap_64(mem_total); | ||
1875 | mem_free = bswap_64(mem_free); | ||
1876 | } | ||
1877 | |||
1878 | strbuf_addf(&sb, "%u:%"PRIu64":%"PRIu64":", | ||
1879 | node, mem_total, mem_free); | ||
1880 | |||
1881 | str = do_read_string(fd, ph); | ||
1882 | if (!str) | ||
1883 | goto error; | ||
1884 | |||
1885 | /* include a NULL character at the end */ | ||
1886 | strbuf_add(&sb, str, strlen(str) + 1); | ||
1887 | free(str); | ||
1888 | } | ||
1889 | ph->env.numa_nodes = strbuf_detach(&sb, NULL); | ||
1890 | return 0; | ||
1891 | |||
1892 | error: | ||
1893 | strbuf_release(&sb); | ||
1894 | return -1; | ||
1895 | } | ||
1896 | |||
1897 | static int process_pmu_mappings(struct perf_file_section *section __maybe_unused, | ||
1898 | struct perf_header *ph, int fd, | ||
1899 | void *data __maybe_unused) | ||
1900 | { | ||
1901 | size_t ret; | ||
1902 | char *name; | ||
1903 | u32 pmu_num; | ||
1904 | u32 type; | ||
1905 | struct strbuf sb; | ||
1906 | |||
1907 | ret = read(fd, &pmu_num, sizeof(pmu_num)); | ||
1908 | if (ret != sizeof(pmu_num)) | ||
1909 | return -1; | ||
1910 | |||
1911 | if (ph->needs_swap) | ||
1912 | pmu_num = bswap_32(pmu_num); | ||
1913 | |||
1914 | if (!pmu_num) { | ||
1915 | pr_debug("pmu mappings not available\n"); | ||
1916 | return 0; | ||
1917 | } | ||
1918 | |||
1919 | ph->env.nr_pmu_mappings = pmu_num; | ||
1920 | strbuf_init(&sb, 128); | ||
1921 | |||
1922 | while (pmu_num) { | ||
1923 | if (read(fd, &type, sizeof(type)) != sizeof(type)) | ||
1924 | goto error; | ||
1925 | if (ph->needs_swap) | ||
1926 | type = bswap_32(type); | ||
1927 | |||
1928 | name = do_read_string(fd, ph); | ||
1929 | if (!name) | ||
1930 | goto error; | ||
1931 | |||
1932 | strbuf_addf(&sb, "%u:%s", type, name); | ||
1933 | /* include a NULL character at the end */ | ||
1934 | strbuf_add(&sb, "", 1); | ||
1935 | |||
1936 | free(name); | ||
1937 | pmu_num--; | ||
1938 | } | ||
1939 | ph->env.pmu_mappings = strbuf_detach(&sb, NULL); | ||
1940 | return 0; | ||
1941 | |||
1942 | error: | ||
1943 | strbuf_release(&sb); | ||
1944 | return -1; | ||
1945 | } | ||
1946 | |||
1726 | struct feature_ops { | 1947 | struct feature_ops { |
1727 | int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist); | 1948 | int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist); |
1728 | void (*print)(struct perf_header *h, int fd, FILE *fp); | 1949 | void (*print)(struct perf_header *h, int fd, FILE *fp); |
1729 | int (*process)(struct perf_file_section *section, | 1950 | int (*process)(struct perf_file_section *section, |
1730 | struct perf_header *h, int feat, int fd, void *data); | 1951 | struct perf_header *h, int fd, void *data); |
1731 | const char *name; | 1952 | const char *name; |
1732 | bool full_only; | 1953 | bool full_only; |
1733 | }; | 1954 | }; |
@@ -1739,7 +1960,7 @@ struct feature_ops { | |||
1739 | .process = process_##func } | 1960 | .process = process_##func } |
1740 | #define FEAT_OPF(n, func) \ | 1961 | #define FEAT_OPF(n, func) \ |
1741 | [n] = { .name = #n, .write = write_##func, .print = print_##func, \ | 1962 | [n] = { .name = #n, .write = write_##func, .print = print_##func, \ |
1742 | .full_only = true } | 1963 | .process = process_##func, .full_only = true } |
1743 | 1964 | ||
1744 | /* feature_ops not implemented: */ | 1965 | /* feature_ops not implemented: */ |
1745 | #define print_tracing_data NULL | 1966 | #define print_tracing_data NULL |
@@ -1748,20 +1969,20 @@ struct feature_ops { | |||
1748 | static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = { | 1969 | static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = { |
1749 | FEAT_OPP(HEADER_TRACING_DATA, tracing_data), | 1970 | FEAT_OPP(HEADER_TRACING_DATA, tracing_data), |
1750 | FEAT_OPP(HEADER_BUILD_ID, build_id), | 1971 | FEAT_OPP(HEADER_BUILD_ID, build_id), |
1751 | FEAT_OPA(HEADER_HOSTNAME, hostname), | 1972 | FEAT_OPP(HEADER_HOSTNAME, hostname), |
1752 | FEAT_OPA(HEADER_OSRELEASE, osrelease), | 1973 | FEAT_OPP(HEADER_OSRELEASE, osrelease), |
1753 | FEAT_OPA(HEADER_VERSION, version), | 1974 | FEAT_OPP(HEADER_VERSION, version), |
1754 | FEAT_OPA(HEADER_ARCH, arch), | 1975 | FEAT_OPP(HEADER_ARCH, arch), |
1755 | FEAT_OPA(HEADER_NRCPUS, nrcpus), | 1976 | FEAT_OPP(HEADER_NRCPUS, nrcpus), |
1756 | FEAT_OPA(HEADER_CPUDESC, cpudesc), | 1977 | FEAT_OPP(HEADER_CPUDESC, cpudesc), |
1757 | FEAT_OPA(HEADER_CPUID, cpuid), | 1978 | FEAT_OPP(HEADER_CPUID, cpuid), |
1758 | FEAT_OPA(HEADER_TOTAL_MEM, total_mem), | 1979 | FEAT_OPP(HEADER_TOTAL_MEM, total_mem), |
1759 | FEAT_OPP(HEADER_EVENT_DESC, event_desc), | 1980 | FEAT_OPP(HEADER_EVENT_DESC, event_desc), |
1760 | FEAT_OPA(HEADER_CMDLINE, cmdline), | 1981 | FEAT_OPP(HEADER_CMDLINE, cmdline), |
1761 | FEAT_OPF(HEADER_CPU_TOPOLOGY, cpu_topology), | 1982 | FEAT_OPF(HEADER_CPU_TOPOLOGY, cpu_topology), |
1762 | FEAT_OPF(HEADER_NUMA_TOPOLOGY, numa_topology), | 1983 | FEAT_OPF(HEADER_NUMA_TOPOLOGY, numa_topology), |
1763 | FEAT_OPA(HEADER_BRANCH_STACK, branch_stack), | 1984 | FEAT_OPA(HEADER_BRANCH_STACK, branch_stack), |
1764 | FEAT_OPA(HEADER_PMU_MAPPINGS, pmu_mappings), | 1985 | FEAT_OPP(HEADER_PMU_MAPPINGS, pmu_mappings), |
1765 | }; | 1986 | }; |
1766 | 1987 | ||
1767 | struct header_print_data { | 1988 | struct header_print_data { |
@@ -2241,7 +2462,7 @@ static int perf_file_section__process(struct perf_file_section *section, | |||
2241 | if (!feat_ops[feat].process) | 2462 | if (!feat_ops[feat].process) |
2242 | return 0; | 2463 | return 0; |
2243 | 2464 | ||
2244 | return feat_ops[feat].process(section, ph, feat, fd, data); | 2465 | return feat_ops[feat].process(section, ph, fd, data); |
2245 | } | 2466 | } |
2246 | 2467 | ||
2247 | static int perf_file_header__read_pipe(struct perf_pipe_file_header *header, | 2468 | static int perf_file_header__read_pipe(struct perf_pipe_file_header *header, |
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index 209dad4fee2b..99bdd3abce59 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h | |||
@@ -58,6 +58,29 @@ struct perf_header; | |||
58 | int perf_file_header__read(struct perf_file_header *header, | 58 | int perf_file_header__read(struct perf_file_header *header, |
59 | struct perf_header *ph, int fd); | 59 | struct perf_header *ph, int fd); |
60 | 60 | ||
61 | struct perf_session_env { | ||
62 | char *hostname; | ||
63 | char *os_release; | ||
64 | char *version; | ||
65 | char *arch; | ||
66 | int nr_cpus_online; | ||
67 | int nr_cpus_avail; | ||
68 | char *cpu_desc; | ||
69 | char *cpuid; | ||
70 | unsigned long long total_mem; | ||
71 | |||
72 | int nr_cmdline; | ||
73 | char *cmdline; | ||
74 | int nr_sibling_cores; | ||
75 | char *sibling_cores; | ||
76 | int nr_sibling_threads; | ||
77 | char *sibling_threads; | ||
78 | int nr_numa_nodes; | ||
79 | char *numa_nodes; | ||
80 | int nr_pmu_mappings; | ||
81 | char *pmu_mappings; | ||
82 | }; | ||
83 | |||
61 | struct perf_header { | 84 | struct perf_header { |
62 | int frozen; | 85 | int frozen; |
63 | bool needs_swap; | 86 | bool needs_swap; |
@@ -67,6 +90,7 @@ struct perf_header { | |||
67 | u64 event_offset; | 90 | u64 event_offset; |
68 | u64 event_size; | 91 | u64 event_size; |
69 | DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS); | 92 | DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS); |
93 | struct perf_session_env env; | ||
70 | }; | 94 | }; |
71 | 95 | ||
72 | struct perf_evlist; | 96 | struct perf_evlist; |
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index b442ee49452b..ead5316b3f89 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c | |||
@@ -243,15 +243,14 @@ size_t map__fprintf(struct map *self, FILE *fp) | |||
243 | 243 | ||
244 | size_t map__fprintf_dsoname(struct map *map, FILE *fp) | 244 | size_t map__fprintf_dsoname(struct map *map, FILE *fp) |
245 | { | 245 | { |
246 | const char *dsoname; | 246 | const char *dsoname = "[unknown]"; |
247 | 247 | ||
248 | if (map && map->dso && (map->dso->name || map->dso->long_name)) { | 248 | if (map && map->dso && (map->dso->name || map->dso->long_name)) { |
249 | if (symbol_conf.show_kernel_path && map->dso->long_name) | 249 | if (symbol_conf.show_kernel_path && map->dso->long_name) |
250 | dsoname = map->dso->long_name; | 250 | dsoname = map->dso->long_name; |
251 | else if (map->dso->name) | 251 | else if (map->dso->name) |
252 | dsoname = map->dso->name; | 252 | dsoname = map->dso->name; |
253 | } else | 253 | } |
254 | dsoname = "[unknown]"; | ||
255 | 254 | ||
256 | return fprintf(fp, "%s", dsoname); | 255 | return fprintf(fp, "%s", dsoname); |
257 | } | 256 | } |
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 4ce04c2281d3..49a256e6e0a2 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
@@ -1100,6 +1100,7 @@ static int parse_probe_trace_command(const char *cmd, | |||
1100 | struct probe_trace_point *tp = &tev->point; | 1100 | struct probe_trace_point *tp = &tev->point; |
1101 | char pr; | 1101 | char pr; |
1102 | char *p; | 1102 | char *p; |
1103 | char *argv0_str = NULL, *fmt, *fmt1_str, *fmt2_str, *fmt3_str; | ||
1103 | int ret, i, argc; | 1104 | int ret, i, argc; |
1104 | char **argv; | 1105 | char **argv; |
1105 | 1106 | ||
@@ -1116,14 +1117,27 @@ static int parse_probe_trace_command(const char *cmd, | |||
1116 | } | 1117 | } |
1117 | 1118 | ||
1118 | /* Scan event and group name. */ | 1119 | /* Scan event and group name. */ |
1119 | ret = sscanf(argv[0], "%c:%a[^/ \t]/%a[^ \t]", | 1120 | argv0_str = strdup(argv[0]); |
1120 | &pr, (float *)(void *)&tev->group, | 1121 | if (argv0_str == NULL) { |
1121 | (float *)(void *)&tev->event); | 1122 | ret = -ENOMEM; |
1122 | if (ret != 3) { | 1123 | goto out; |
1124 | } | ||
1125 | fmt1_str = strtok_r(argv0_str, ":", &fmt); | ||
1126 | fmt2_str = strtok_r(NULL, "/", &fmt); | ||
1127 | fmt3_str = strtok_r(NULL, " \t", &fmt); | ||
1128 | if (fmt1_str == NULL || strlen(fmt1_str) != 1 || fmt2_str == NULL | ||
1129 | || fmt3_str == NULL) { | ||
1123 | semantic_error("Failed to parse event name: %s\n", argv[0]); | 1130 | semantic_error("Failed to parse event name: %s\n", argv[0]); |
1124 | ret = -EINVAL; | 1131 | ret = -EINVAL; |
1125 | goto out; | 1132 | goto out; |
1126 | } | 1133 | } |
1134 | pr = fmt1_str[0]; | ||
1135 | tev->group = strdup(fmt2_str); | ||
1136 | tev->event = strdup(fmt3_str); | ||
1137 | if (tev->group == NULL || tev->event == NULL) { | ||
1138 | ret = -ENOMEM; | ||
1139 | goto out; | ||
1140 | } | ||
1127 | pr_debug("Group:%s Event:%s probe:%c\n", tev->group, tev->event, pr); | 1141 | pr_debug("Group:%s Event:%s probe:%c\n", tev->group, tev->event, pr); |
1128 | 1142 | ||
1129 | tp->retprobe = (pr == 'r'); | 1143 | tp->retprobe = (pr == 'r'); |
@@ -1135,10 +1149,17 @@ static int parse_probe_trace_command(const char *cmd, | |||
1135 | p++; | 1149 | p++; |
1136 | } else | 1150 | } else |
1137 | p = argv[1]; | 1151 | p = argv[1]; |
1138 | ret = sscanf(p, "%a[^+]+%lu", (float *)(void *)&tp->symbol, | 1152 | fmt1_str = strtok_r(p, "+", &fmt); |
1139 | &tp->offset); | 1153 | tp->symbol = strdup(fmt1_str); |
1140 | if (ret == 1) | 1154 | if (tp->symbol == NULL) { |
1155 | ret = -ENOMEM; | ||
1156 | goto out; | ||
1157 | } | ||
1158 | fmt2_str = strtok_r(NULL, "", &fmt); | ||
1159 | if (fmt2_str == NULL) | ||
1141 | tp->offset = 0; | 1160 | tp->offset = 0; |
1161 | else | ||
1162 | tp->offset = strtoul(fmt2_str, NULL, 10); | ||
1142 | 1163 | ||
1143 | tev->nargs = argc - 2; | 1164 | tev->nargs = argc - 2; |
1144 | tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs); | 1165 | tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs); |
@@ -1162,6 +1183,7 @@ static int parse_probe_trace_command(const char *cmd, | |||
1162 | } | 1183 | } |
1163 | ret = 0; | 1184 | ret = 0; |
1164 | out: | 1185 | out: |
1186 | free(argv0_str); | ||
1165 | argv_free(argv); | 1187 | argv_free(argv); |
1166 | return ret; | 1188 | return ret; |
1167 | } | 1189 | } |
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c index ffde3e4e34aa..f80605eb1855 100644 --- a/tools/perf/util/scripting-engines/trace-event-perl.c +++ b/tools/perf/util/scripting-engines/trace-event-perl.c | |||
@@ -282,7 +282,7 @@ static void perl_process_tracepoint(union perf_event *perf_event __maybe_unused, | |||
282 | 282 | ||
283 | event = find_cache_event(evsel); | 283 | event = find_cache_event(evsel); |
284 | if (!event) | 284 | if (!event) |
285 | die("ug! no event found for type %d", evsel->attr.config); | 285 | die("ug! no event found for type %" PRIu64, evsel->attr.config); |
286 | 286 | ||
287 | pid = raw_field_value(event, "common_pid", data); | 287 | pid = raw_field_value(event, "common_pid", data); |
288 | 288 | ||
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 4ff45e30c726..b441b07172b7 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
@@ -34,6 +34,7 @@ static inline char *bfd_demangle(void __maybe_unused *v, | |||
34 | return NULL; | 34 | return NULL; |
35 | } | 35 | } |
36 | #else | 36 | #else |
37 | #define PACKAGE 'perf' | ||
37 | #include <bfd.h> | 38 | #include <bfd.h> |
38 | #endif | 39 | #endif |
39 | #endif | 40 | #endif |
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index 70c2c13ff679..f66610b7bacf 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h | |||
@@ -16,6 +16,8 @@ struct thread { | |||
16 | bool comm_set; | 16 | bool comm_set; |
17 | char *comm; | 17 | char *comm; |
18 | int comm_len; | 18 | int comm_len; |
19 | |||
20 | void *priv; | ||
19 | }; | 21 | }; |
20 | 22 | ||
21 | struct machine; | 23 | struct machine; |
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index aa4c860a21d1..3aabcd687cd5 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c | |||
@@ -229,24 +229,22 @@ void parse_proc_kallsyms(struct pevent *pevent, | |||
229 | char *next = NULL; | 229 | char *next = NULL; |
230 | char *addr_str; | 230 | char *addr_str; |
231 | char *mod; | 231 | char *mod; |
232 | char ch; | 232 | char *fmt; |
233 | 233 | ||
234 | line = strtok_r(file, "\n", &next); | 234 | line = strtok_r(file, "\n", &next); |
235 | while (line) { | 235 | while (line) { |
236 | mod = NULL; | 236 | mod = NULL; |
237 | sscanf(line, "%as %c %as\t[%as", | 237 | addr_str = strtok_r(line, " ", &fmt); |
238 | (float *)(void *)&addr_str, /* workaround gcc warning */ | ||
239 | &ch, (float *)(void *)&func, (float *)(void *)&mod); | ||
240 | addr = strtoull(addr_str, NULL, 16); | 238 | addr = strtoull(addr_str, NULL, 16); |
241 | free(addr_str); | 239 | /* skip character */ |
242 | 240 | strtok_r(NULL, " ", &fmt); | |
243 | /* truncate the extra ']' */ | 241 | func = strtok_r(NULL, "\t", &fmt); |
242 | mod = strtok_r(NULL, "]", &fmt); | ||
243 | /* truncate the extra '[' */ | ||
244 | if (mod) | 244 | if (mod) |
245 | mod[strlen(mod) - 1] = 0; | 245 | mod = mod + 1; |
246 | 246 | ||
247 | pevent_register_function(pevent, func, addr, mod); | 247 | pevent_register_function(pevent, func, addr, mod); |
248 | free(func); | ||
249 | free(mod); | ||
250 | 248 | ||
251 | line = strtok_r(NULL, "\n", &next); | 249 | line = strtok_r(NULL, "\n", &next); |
252 | } | 250 | } |