diff options
Diffstat (limited to 'tools/perf/util/header.c')
-rw-r--r-- | tools/perf/util/header.c | 403 |
1 files changed, 320 insertions, 83 deletions
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index e306857b2c2b..4805e6dfd23c 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -2,9 +2,15 @@ | |||
2 | #include <unistd.h> | 2 | #include <unistd.h> |
3 | #include <stdio.h> | 3 | #include <stdio.h> |
4 | #include <stdlib.h> | 4 | #include <stdlib.h> |
5 | #include <linux/list.h> | ||
5 | 6 | ||
6 | #include "util.h" | 7 | #include "util.h" |
7 | #include "header.h" | 8 | #include "header.h" |
9 | #include "../perf.h" | ||
10 | #include "trace-event.h" | ||
11 | #include "symbol.h" | ||
12 | #include "data_map.h" | ||
13 | #include "debug.h" | ||
8 | 14 | ||
9 | /* | 15 | /* |
10 | * Create new perf.data header attribute: | 16 | * Create new perf.data header attribute: |
@@ -13,32 +19,43 @@ struct perf_header_attr *perf_header_attr__new(struct perf_event_attr *attr) | |||
13 | { | 19 | { |
14 | struct perf_header_attr *self = malloc(sizeof(*self)); | 20 | struct perf_header_attr *self = malloc(sizeof(*self)); |
15 | 21 | ||
16 | if (!self) | 22 | if (self != NULL) { |
17 | die("nomem"); | 23 | self->attr = *attr; |
18 | 24 | self->ids = 0; | |
19 | self->attr = *attr; | 25 | self->size = 1; |
20 | self->ids = 0; | 26 | self->id = malloc(sizeof(u64)); |
21 | self->size = 1; | 27 | if (self->id == NULL) { |
22 | self->id = malloc(sizeof(u64)); | 28 | free(self); |
23 | 29 | self = NULL; | |
24 | if (!self->id) | 30 | } |
25 | die("nomem"); | 31 | } |
26 | 32 | ||
27 | return self; | 33 | return self; |
28 | } | 34 | } |
29 | 35 | ||
30 | void perf_header_attr__add_id(struct perf_header_attr *self, u64 id) | 36 | void perf_header_attr__delete(struct perf_header_attr *self) |
37 | { | ||
38 | free(self->id); | ||
39 | free(self); | ||
40 | } | ||
41 | |||
42 | int perf_header_attr__add_id(struct perf_header_attr *self, u64 id) | ||
31 | { | 43 | { |
32 | int pos = self->ids; | 44 | int pos = self->ids; |
33 | 45 | ||
34 | self->ids++; | 46 | self->ids++; |
35 | if (self->ids > self->size) { | 47 | if (self->ids > self->size) { |
36 | self->size *= 2; | 48 | int nsize = self->size * 2; |
37 | self->id = realloc(self->id, self->size * sizeof(u64)); | 49 | u64 *nid = realloc(self->id, nsize * sizeof(u64)); |
38 | if (!self->id) | 50 | |
39 | die("nomem"); | 51 | if (nid == NULL) |
52 | return -1; | ||
53 | |||
54 | self->size = nsize; | ||
55 | self->id = nid; | ||
40 | } | 56 | } |
41 | self->id[pos] = id; | 57 | self->id[pos] = id; |
58 | return 0; | ||
42 | } | 59 | } |
43 | 60 | ||
44 | /* | 61 | /* |
@@ -46,42 +63,52 @@ void perf_header_attr__add_id(struct perf_header_attr *self, u64 id) | |||
46 | */ | 63 | */ |
47 | struct perf_header *perf_header__new(void) | 64 | struct perf_header *perf_header__new(void) |
48 | { | 65 | { |
49 | struct perf_header *self = malloc(sizeof(*self)); | 66 | struct perf_header *self = zalloc(sizeof(*self)); |
50 | 67 | ||
51 | if (!self) | 68 | if (self != NULL) { |
52 | die("nomem"); | 69 | self->size = 1; |
70 | self->attr = malloc(sizeof(void *)); | ||
53 | 71 | ||
54 | self->frozen = 0; | 72 | if (self->attr == NULL) { |
73 | free(self); | ||
74 | self = NULL; | ||
75 | } | ||
76 | } | ||
55 | 77 | ||
56 | self->attrs = 0; | 78 | return self; |
57 | self->size = 1; | 79 | } |
58 | self->attr = malloc(sizeof(void *)); | ||
59 | 80 | ||
60 | if (!self->attr) | 81 | void perf_header__delete(struct perf_header *self) |
61 | die("nomem"); | 82 | { |
83 | int i; | ||
62 | 84 | ||
63 | self->data_offset = 0; | 85 | for (i = 0; i < self->attrs; ++i) |
64 | self->data_size = 0; | 86 | perf_header_attr__delete(self->attr[i]); |
65 | 87 | ||
66 | return self; | 88 | free(self->attr); |
89 | free(self); | ||
67 | } | 90 | } |
68 | 91 | ||
69 | void perf_header__add_attr(struct perf_header *self, | 92 | int perf_header__add_attr(struct perf_header *self, |
70 | struct perf_header_attr *attr) | 93 | struct perf_header_attr *attr) |
71 | { | 94 | { |
72 | int pos = self->attrs; | ||
73 | |||
74 | if (self->frozen) | 95 | if (self->frozen) |
75 | die("frozen"); | 96 | return -1; |
76 | 97 | ||
77 | self->attrs++; | 98 | if (self->attrs == self->size) { |
78 | if (self->attrs > self->size) { | 99 | int nsize = self->size * 2; |
79 | self->size *= 2; | 100 | struct perf_header_attr **nattr; |
80 | self->attr = realloc(self->attr, self->size * sizeof(void *)); | 101 | |
81 | if (!self->attr) | 102 | nattr = realloc(self->attr, nsize * sizeof(void *)); |
82 | die("nomem"); | 103 | if (nattr == NULL) |
104 | return -1; | ||
105 | |||
106 | self->size = nsize; | ||
107 | self->attr = nattr; | ||
83 | } | 108 | } |
84 | self->attr[pos] = attr; | 109 | |
110 | self->attr[self->attrs++] = attr; | ||
111 | return 0; | ||
85 | } | 112 | } |
86 | 113 | ||
87 | #define MAX_EVENT_NAME 64 | 114 | #define MAX_EVENT_NAME 64 |
@@ -97,7 +124,7 @@ static struct perf_trace_event_type *events; | |||
97 | void perf_header__push_event(u64 id, const char *name) | 124 | void perf_header__push_event(u64 id, const char *name) |
98 | { | 125 | { |
99 | if (strlen(name) > MAX_EVENT_NAME) | 126 | if (strlen(name) > MAX_EVENT_NAME) |
100 | printf("Event %s will be truncated\n", name); | 127 | pr_warning("Event %s will be truncated\n", name); |
101 | 128 | ||
102 | if (!events) { | 129 | if (!events) { |
103 | events = malloc(sizeof(struct perf_trace_event_type)); | 130 | events = malloc(sizeof(struct perf_trace_event_type)); |
@@ -128,44 +155,137 @@ static const char *__perf_magic = "PERFFILE"; | |||
128 | 155 | ||
129 | #define PERF_MAGIC (*(u64 *)__perf_magic) | 156 | #define PERF_MAGIC (*(u64 *)__perf_magic) |
130 | 157 | ||
131 | struct perf_file_section { | ||
132 | u64 offset; | ||
133 | u64 size; | ||
134 | }; | ||
135 | |||
136 | struct perf_file_attr { | 158 | struct perf_file_attr { |
137 | struct perf_event_attr attr; | 159 | struct perf_event_attr attr; |
138 | struct perf_file_section ids; | 160 | struct perf_file_section ids; |
139 | }; | 161 | }; |
140 | 162 | ||
141 | struct perf_file_header { | 163 | void perf_header__set_feat(struct perf_header *self, int feat) |
142 | u64 magic; | 164 | { |
143 | u64 size; | 165 | set_bit(feat, self->adds_features); |
144 | u64 attr_size; | 166 | } |
145 | struct perf_file_section attrs; | ||
146 | struct perf_file_section data; | ||
147 | struct perf_file_section event_types; | ||
148 | }; | ||
149 | 167 | ||
150 | static void do_write(int fd, void *buf, size_t size) | 168 | bool perf_header__has_feat(const struct perf_header *self, int feat) |
169 | { | ||
170 | return test_bit(feat, self->adds_features); | ||
171 | } | ||
172 | |||
173 | static int do_write(int fd, const void *buf, size_t size) | ||
151 | { | 174 | { |
152 | while (size) { | 175 | while (size) { |
153 | int ret = write(fd, buf, size); | 176 | int ret = write(fd, buf, size); |
154 | 177 | ||
155 | if (ret < 0) | 178 | if (ret < 0) |
156 | die("failed to write"); | 179 | return -errno; |
157 | 180 | ||
158 | size -= ret; | 181 | size -= ret; |
159 | buf += ret; | 182 | buf += ret; |
160 | } | 183 | } |
184 | |||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | static int __dsos__write_buildid_table(struct list_head *head, int fd) | ||
189 | { | ||
190 | struct dso *pos; | ||
191 | |||
192 | list_for_each_entry(pos, head, node) { | ||
193 | int err; | ||
194 | struct build_id_event b; | ||
195 | size_t len; | ||
196 | |||
197 | if (!pos->has_build_id) | ||
198 | continue; | ||
199 | len = pos->long_name_len + 1; | ||
200 | len = ALIGN(len, 64); | ||
201 | memset(&b, 0, sizeof(b)); | ||
202 | memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id)); | ||
203 | b.header.size = sizeof(b) + len; | ||
204 | err = do_write(fd, &b, sizeof(b)); | ||
205 | if (err < 0) | ||
206 | return err; | ||
207 | err = do_write(fd, pos->long_name, len); | ||
208 | if (err < 0) | ||
209 | return err; | ||
210 | } | ||
211 | |||
212 | return 0; | ||
161 | } | 213 | } |
162 | 214 | ||
163 | void perf_header__write(struct perf_header *self, int fd) | 215 | static int dsos__write_buildid_table(int fd) |
216 | { | ||
217 | int err = __dsos__write_buildid_table(&dsos__kernel, fd); | ||
218 | if (err == 0) | ||
219 | err = __dsos__write_buildid_table(&dsos__user, fd); | ||
220 | return err; | ||
221 | } | ||
222 | |||
223 | static int perf_header__adds_write(struct perf_header *self, int fd) | ||
224 | { | ||
225 | int nr_sections; | ||
226 | struct perf_file_section *feat_sec; | ||
227 | int sec_size; | ||
228 | u64 sec_start; | ||
229 | int idx = 0, err; | ||
230 | |||
231 | if (dsos__read_build_ids()) | ||
232 | perf_header__set_feat(self, HEADER_BUILD_ID); | ||
233 | |||
234 | nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS); | ||
235 | if (!nr_sections) | ||
236 | return 0; | ||
237 | |||
238 | feat_sec = calloc(sizeof(*feat_sec), nr_sections); | ||
239 | if (feat_sec == NULL) | ||
240 | return -ENOMEM; | ||
241 | |||
242 | sec_size = sizeof(*feat_sec) * nr_sections; | ||
243 | |||
244 | sec_start = self->data_offset + self->data_size; | ||
245 | lseek(fd, sec_start + sec_size, SEEK_SET); | ||
246 | |||
247 | if (perf_header__has_feat(self, HEADER_TRACE_INFO)) { | ||
248 | struct perf_file_section *trace_sec; | ||
249 | |||
250 | trace_sec = &feat_sec[idx++]; | ||
251 | |||
252 | /* Write trace info */ | ||
253 | trace_sec->offset = lseek(fd, 0, SEEK_CUR); | ||
254 | read_tracing_data(fd, attrs, nr_counters); | ||
255 | trace_sec->size = lseek(fd, 0, SEEK_CUR) - trace_sec->offset; | ||
256 | } | ||
257 | |||
258 | |||
259 | if (perf_header__has_feat(self, HEADER_BUILD_ID)) { | ||
260 | struct perf_file_section *buildid_sec; | ||
261 | |||
262 | buildid_sec = &feat_sec[idx++]; | ||
263 | |||
264 | /* Write build-ids */ | ||
265 | buildid_sec->offset = lseek(fd, 0, SEEK_CUR); | ||
266 | err = dsos__write_buildid_table(fd); | ||
267 | if (err < 0) { | ||
268 | pr_debug("failed to write buildid table\n"); | ||
269 | goto out_free; | ||
270 | } | ||
271 | buildid_sec->size = lseek(fd, 0, SEEK_CUR) - buildid_sec->offset; | ||
272 | } | ||
273 | |||
274 | lseek(fd, sec_start, SEEK_SET); | ||
275 | err = do_write(fd, feat_sec, sec_size); | ||
276 | if (err < 0) | ||
277 | pr_debug("failed to write feature section\n"); | ||
278 | out_free: | ||
279 | free(feat_sec); | ||
280 | return err; | ||
281 | } | ||
282 | |||
283 | int perf_header__write(struct perf_header *self, int fd, bool at_exit) | ||
164 | { | 284 | { |
165 | struct perf_file_header f_header; | 285 | struct perf_file_header f_header; |
166 | struct perf_file_attr f_attr; | 286 | struct perf_file_attr f_attr; |
167 | struct perf_header_attr *attr; | 287 | struct perf_header_attr *attr; |
168 | int i; | 288 | int i, err; |
169 | 289 | ||
170 | lseek(fd, sizeof(f_header), SEEK_SET); | 290 | lseek(fd, sizeof(f_header), SEEK_SET); |
171 | 291 | ||
@@ -174,7 +294,11 @@ void perf_header__write(struct perf_header *self, int fd) | |||
174 | attr = self->attr[i]; | 294 | attr = self->attr[i]; |
175 | 295 | ||
176 | attr->id_offset = lseek(fd, 0, SEEK_CUR); | 296 | attr->id_offset = lseek(fd, 0, SEEK_CUR); |
177 | do_write(fd, attr->id, attr->ids * sizeof(u64)); | 297 | err = do_write(fd, attr->id, attr->ids * sizeof(u64)); |
298 | if (err < 0) { | ||
299 | pr_debug("failed to write perf header\n"); | ||
300 | return err; | ||
301 | } | ||
178 | } | 302 | } |
179 | 303 | ||
180 | 304 | ||
@@ -190,17 +314,31 @@ void perf_header__write(struct perf_header *self, int fd) | |||
190 | .size = attr->ids * sizeof(u64), | 314 | .size = attr->ids * sizeof(u64), |
191 | } | 315 | } |
192 | }; | 316 | }; |
193 | do_write(fd, &f_attr, sizeof(f_attr)); | 317 | err = do_write(fd, &f_attr, sizeof(f_attr)); |
318 | if (err < 0) { | ||
319 | pr_debug("failed to write perf header attribute\n"); | ||
320 | return err; | ||
321 | } | ||
194 | } | 322 | } |
195 | 323 | ||
196 | self->event_offset = lseek(fd, 0, SEEK_CUR); | 324 | self->event_offset = lseek(fd, 0, SEEK_CUR); |
197 | self->event_size = event_count * sizeof(struct perf_trace_event_type); | 325 | self->event_size = event_count * sizeof(struct perf_trace_event_type); |
198 | if (events) | 326 | if (events) { |
199 | do_write(fd, events, self->event_size); | 327 | err = do_write(fd, events, self->event_size); |
200 | 328 | if (err < 0) { | |
329 | pr_debug("failed to write perf header events\n"); | ||
330 | return err; | ||
331 | } | ||
332 | } | ||
201 | 333 | ||
202 | self->data_offset = lseek(fd, 0, SEEK_CUR); | 334 | self->data_offset = lseek(fd, 0, SEEK_CUR); |
203 | 335 | ||
336 | if (at_exit) { | ||
337 | err = perf_header__adds_write(self, fd); | ||
338 | if (err < 0) | ||
339 | return err; | ||
340 | } | ||
341 | |||
204 | f_header = (struct perf_file_header){ | 342 | f_header = (struct perf_file_header){ |
205 | .magic = PERF_MAGIC, | 343 | .magic = PERF_MAGIC, |
206 | .size = sizeof(f_header), | 344 | .size = sizeof(f_header), |
@@ -219,11 +357,18 @@ void perf_header__write(struct perf_header *self, int fd) | |||
219 | }, | 357 | }, |
220 | }; | 358 | }; |
221 | 359 | ||
360 | memcpy(&f_header.adds_features, &self->adds_features, sizeof(self->adds_features)); | ||
361 | |||
222 | lseek(fd, 0, SEEK_SET); | 362 | lseek(fd, 0, SEEK_SET); |
223 | do_write(fd, &f_header, sizeof(f_header)); | 363 | err = do_write(fd, &f_header, sizeof(f_header)); |
364 | if (err < 0) { | ||
365 | pr_debug("failed to write perf header\n"); | ||
366 | return err; | ||
367 | } | ||
224 | lseek(fd, self->data_offset + self->data_size, SEEK_SET); | 368 | lseek(fd, self->data_offset + self->data_size, SEEK_SET); |
225 | 369 | ||
226 | self->frozen = 1; | 370 | self->frozen = 1; |
371 | return 0; | ||
227 | } | 372 | } |
228 | 373 | ||
229 | static void do_read(int fd, void *buf, size_t size) | 374 | static void do_read(int fd, void *buf, size_t size) |
@@ -241,22 +386,109 @@ static void do_read(int fd, void *buf, size_t size) | |||
241 | } | 386 | } |
242 | } | 387 | } |
243 | 388 | ||
244 | struct perf_header *perf_header__read(int fd) | 389 | int perf_header__process_sections(struct perf_header *self, int fd, |
390 | int (*process)(struct perf_file_section *self, | ||
391 | int feat, int fd)) | ||
392 | { | ||
393 | struct perf_file_section *feat_sec; | ||
394 | int nr_sections; | ||
395 | int sec_size; | ||
396 | int idx = 0; | ||
397 | int err = 0, feat = 1; | ||
398 | |||
399 | nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS); | ||
400 | if (!nr_sections) | ||
401 | return 0; | ||
402 | |||
403 | feat_sec = calloc(sizeof(*feat_sec), nr_sections); | ||
404 | if (!feat_sec) | ||
405 | return -1; | ||
406 | |||
407 | sec_size = sizeof(*feat_sec) * nr_sections; | ||
408 | |||
409 | lseek(fd, self->data_offset + self->data_size, SEEK_SET); | ||
410 | |||
411 | do_read(fd, feat_sec, sec_size); | ||
412 | |||
413 | while (idx < nr_sections && feat < HEADER_LAST_FEATURE) { | ||
414 | if (perf_header__has_feat(self, feat)) { | ||
415 | struct perf_file_section *sec = &feat_sec[idx++]; | ||
416 | |||
417 | err = process(sec, feat, fd); | ||
418 | if (err < 0) | ||
419 | break; | ||
420 | } | ||
421 | ++feat; | ||
422 | } | ||
423 | |||
424 | free(feat_sec); | ||
425 | return err; | ||
426 | }; | ||
427 | |||
428 | int perf_file_header__read(struct perf_file_header *self, | ||
429 | struct perf_header *ph, int fd) | ||
430 | { | ||
431 | lseek(fd, 0, SEEK_SET); | ||
432 | do_read(fd, self, sizeof(*self)); | ||
433 | |||
434 | if (self->magic != PERF_MAGIC || | ||
435 | self->attr_size != sizeof(struct perf_file_attr)) | ||
436 | return -1; | ||
437 | |||
438 | if (self->size != sizeof(*self)) { | ||
439 | /* Support the previous format */ | ||
440 | if (self->size == offsetof(typeof(*self), adds_features)) | ||
441 | bitmap_zero(self->adds_features, HEADER_FEAT_BITS); | ||
442 | else | ||
443 | return -1; | ||
444 | } | ||
445 | |||
446 | memcpy(&ph->adds_features, &self->adds_features, | ||
447 | sizeof(self->adds_features)); | ||
448 | |||
449 | ph->event_offset = self->event_types.offset; | ||
450 | ph->event_size = self->event_types.size; | ||
451 | ph->data_offset = self->data.offset; | ||
452 | ph->data_size = self->data.size; | ||
453 | return 0; | ||
454 | } | ||
455 | |||
456 | static int perf_file_section__process(struct perf_file_section *self, | ||
457 | int feat, int fd) | ||
458 | { | ||
459 | if (lseek(fd, self->offset, SEEK_SET) < 0) { | ||
460 | pr_debug("Failed to lseek to %Ld offset for feature %d, " | ||
461 | "continuing...\n", self->offset, feat); | ||
462 | return 0; | ||
463 | } | ||
464 | |||
465 | switch (feat) { | ||
466 | case HEADER_TRACE_INFO: | ||
467 | trace_report(fd); | ||
468 | break; | ||
469 | |||
470 | case HEADER_BUILD_ID: | ||
471 | if (perf_header__read_build_ids(fd, self->offset, self->size)) | ||
472 | pr_debug("Failed to read buildids, continuing...\n"); | ||
473 | break; | ||
474 | default: | ||
475 | pr_debug("unknown feature %d, continuing...\n", feat); | ||
476 | } | ||
477 | |||
478 | return 0; | ||
479 | } | ||
480 | |||
481 | int perf_header__read(struct perf_header *self, int fd) | ||
245 | { | 482 | { |
246 | struct perf_header *self = perf_header__new(); | ||
247 | struct perf_file_header f_header; | 483 | struct perf_file_header f_header; |
248 | struct perf_file_attr f_attr; | 484 | struct perf_file_attr f_attr; |
249 | u64 f_id; | 485 | u64 f_id; |
250 | |||
251 | int nr_attrs, nr_ids, i, j; | 486 | int nr_attrs, nr_ids, i, j; |
252 | 487 | ||
253 | lseek(fd, 0, SEEK_SET); | 488 | if (perf_file_header__read(&f_header, self, fd) < 0) { |
254 | do_read(fd, &f_header, sizeof(f_header)); | 489 | pr_debug("incompatible file format\n"); |
255 | 490 | return -EINVAL; | |
256 | if (f_header.magic != PERF_MAGIC || | 491 | } |
257 | f_header.size != sizeof(f_header) || | ||
258 | f_header.attr_size != sizeof(f_attr)) | ||
259 | die("incompatible file format"); | ||
260 | 492 | ||
261 | nr_attrs = f_header.attrs.size / sizeof(f_attr); | 493 | nr_attrs = f_header.attrs.size / sizeof(f_attr); |
262 | lseek(fd, f_header.attrs.offset, SEEK_SET); | 494 | lseek(fd, f_header.attrs.offset, SEEK_SET); |
@@ -269,6 +501,8 @@ struct perf_header *perf_header__read(int fd) | |||
269 | tmp = lseek(fd, 0, SEEK_CUR); | 501 | tmp = lseek(fd, 0, SEEK_CUR); |
270 | 502 | ||
271 | attr = perf_header_attr__new(&f_attr.attr); | 503 | attr = perf_header_attr__new(&f_attr.attr); |
504 | if (attr == NULL) | ||
505 | return -ENOMEM; | ||
272 | 506 | ||
273 | nr_ids = f_attr.ids.size / sizeof(u64); | 507 | nr_ids = f_attr.ids.size / sizeof(u64); |
274 | lseek(fd, f_attr.ids.offset, SEEK_SET); | 508 | lseek(fd, f_attr.ids.offset, SEEK_SET); |
@@ -276,31 +510,34 @@ struct perf_header *perf_header__read(int fd) | |||
276 | for (j = 0; j < nr_ids; j++) { | 510 | for (j = 0; j < nr_ids; j++) { |
277 | do_read(fd, &f_id, sizeof(f_id)); | 511 | do_read(fd, &f_id, sizeof(f_id)); |
278 | 512 | ||
279 | perf_header_attr__add_id(attr, f_id); | 513 | if (perf_header_attr__add_id(attr, f_id) < 0) { |
514 | perf_header_attr__delete(attr); | ||
515 | return -ENOMEM; | ||
516 | } | ||
280 | } | 517 | } |
281 | perf_header__add_attr(self, attr); | 518 | if (perf_header__add_attr(self, attr) < 0) { |
519 | perf_header_attr__delete(attr); | ||
520 | return -ENOMEM; | ||
521 | } | ||
522 | |||
282 | lseek(fd, tmp, SEEK_SET); | 523 | lseek(fd, tmp, SEEK_SET); |
283 | } | 524 | } |
284 | 525 | ||
285 | if (f_header.event_types.size) { | 526 | if (f_header.event_types.size) { |
286 | lseek(fd, f_header.event_types.offset, SEEK_SET); | 527 | lseek(fd, f_header.event_types.offset, SEEK_SET); |
287 | events = malloc(f_header.event_types.size); | 528 | events = malloc(f_header.event_types.size); |
288 | if (!events) | 529 | if (events == NULL) |
289 | die("nomem"); | 530 | return -ENOMEM; |
290 | do_read(fd, events, f_header.event_types.size); | 531 | do_read(fd, events, f_header.event_types.size); |
291 | event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type); | 532 | event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type); |
292 | } | 533 | } |
293 | self->event_offset = f_header.event_types.offset; | ||
294 | self->event_size = f_header.event_types.size; | ||
295 | 534 | ||
296 | self->data_offset = f_header.data.offset; | 535 | perf_header__process_sections(self, fd, perf_file_section__process); |
297 | self->data_size = f_header.data.size; | ||
298 | 536 | ||
299 | lseek(fd, self->data_offset, SEEK_SET); | 537 | lseek(fd, self->data_offset, SEEK_SET); |
300 | 538 | ||
301 | self->frozen = 1; | 539 | self->frozen = 1; |
302 | 540 | return 0; | |
303 | return self; | ||
304 | } | 541 | } |
305 | 542 | ||
306 | u64 perf_header__sample_type(struct perf_header *header) | 543 | u64 perf_header__sample_type(struct perf_header *header) |