aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/perf/builtin-record.c4
-rw-r--r--tools/perf/util/header.c100
-rw-r--r--tools/perf/util/header.h30
3 files changed, 78 insertions, 56 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index fc3709cba136..f0467ff0d8ad 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -574,11 +574,11 @@ static int __cmd_record(int argc, const char **argv)
574 header = perf_header__new(); 574 header = perf_header__new();
575 575
576 if (raw_samples) { 576 if (raw_samples) {
577 perf_header__set_trace_info(); 577 perf_header__feat_trace_info(header);
578 } else { 578 } else {
579 for (i = 0; i < nr_counters; i++) { 579 for (i = 0; i < nr_counters; i++) {
580 if (attrs[i].sample_type & PERF_SAMPLE_RAW) { 580 if (attrs[i].sample_type & PERF_SAMPLE_RAW) {
581 perf_header__set_trace_info(); 581 perf_header__feat_trace_info(header);
582 break; 582 break;
583 } 583 }
584 } 584 }
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 9aae360c0f28..171d51b6f359 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -8,6 +8,8 @@
8#include "../perf.h" 8#include "../perf.h"
9#include "trace-event.h" 9#include "trace-event.h"
10 10
11#include <linux/bitmap.h>
12
11/* 13/*
12 * Create new perf.data header attribute: 14 * Create new perf.data header attribute:
13 */ 15 */
@@ -48,25 +50,17 @@ void perf_header_attr__add_id(struct perf_header_attr *self, u64 id)
48 */ 50 */
49struct perf_header *perf_header__new(void) 51struct perf_header *perf_header__new(void)
50{ 52{
51 struct perf_header *self = malloc(sizeof(*self)); 53 struct perf_header *self = calloc(sizeof(*self), 1);
52 54
53 if (!self) 55 if (!self)
54 die("nomem"); 56 die("nomem");
55 57
56 self->frozen = 0;
57
58 self->attrs = 0;
59 self->size = 1; 58 self->size = 1;
60 self->attr = malloc(sizeof(void *)); 59 self->attr = malloc(sizeof(void *));
61 60
62 if (!self->attr) 61 if (!self->attr)
63 die("nomem"); 62 die("nomem");
64 63
65 self->data_offset = 0;
66 self->data_size = 0;
67 self->trace_info_offset = 0;
68 self->trace_info_size = 0;
69
70 return self; 64 return self;
71} 65}
72 66
@@ -149,14 +143,12 @@ struct perf_file_header {
149 struct perf_file_section attrs; 143 struct perf_file_section attrs;
150 struct perf_file_section data; 144 struct perf_file_section data;
151 struct perf_file_section event_types; 145 struct perf_file_section event_types;
152 struct perf_file_section trace_info; 146 feat_mask_t adds_features;
153}; 147};
154 148
155static int trace_info; 149void perf_header__feat_trace_info(struct perf_header *header)
156
157void perf_header__set_trace_info(void)
158{ 150{
159 trace_info = 1; 151 set_bit(HEADER_TRACE_INFO, perf_header__adds_mask(header));
160} 152}
161 153
162static void do_write(int fd, void *buf, size_t size) 154static void do_write(int fd, void *buf, size_t size)
@@ -172,6 +164,32 @@ static void do_write(int fd, void *buf, size_t size)
172 } 164 }
173} 165}
174 166
167static void perf_header__adds_write(struct perf_header *self, int fd)
168{
169 struct perf_file_section trace_sec;
170 u64 cur_offset = lseek(fd, 0, SEEK_CUR);
171 unsigned long *feat_mask = perf_header__adds_mask(self);
172
173 if (test_bit(HEADER_TRACE_INFO, feat_mask)) {
174 /* Write trace info */
175 trace_sec.offset = lseek(fd, sizeof(trace_sec), SEEK_CUR);
176 read_tracing_data(fd, attrs, nr_counters);
177 trace_sec.size = lseek(fd, 0, SEEK_CUR) - trace_sec.offset;
178
179 /* Write trace info headers */
180 lseek(fd, cur_offset, SEEK_SET);
181 do_write(fd, &trace_sec, sizeof(trace_sec));
182
183 /*
184 * Update cur_offset. So that other (future)
185 * features can set their own infos in this place. But if we are
186 * the only feature, at least that seeks to the place the data
187 * should begin.
188 */
189 cur_offset = lseek(fd, trace_sec.offset + trace_sec.size, SEEK_SET);
190 }
191};
192
175void perf_header__write(struct perf_header *self, int fd) 193void perf_header__write(struct perf_header *self, int fd)
176{ 194{
177 struct perf_file_header f_header; 195 struct perf_file_header f_header;
@@ -210,23 +228,7 @@ void perf_header__write(struct perf_header *self, int fd)
210 if (events) 228 if (events)
211 do_write(fd, events, self->event_size); 229 do_write(fd, events, self->event_size);
212 230
213 if (trace_info) { 231 perf_header__adds_write(self, fd);
214 static int trace_info_written;
215
216 /*
217 * Write it only once
218 */
219 if (!trace_info_written) {
220 self->trace_info_offset = lseek(fd, 0, SEEK_CUR);
221 read_tracing_data(fd, attrs, nr_counters);
222 self->trace_info_size = lseek(fd, 0, SEEK_CUR) -
223 self->trace_info_offset;
224 trace_info_written = 1;
225 } else {
226 lseek(fd, self->trace_info_offset +
227 self->trace_info_size, SEEK_SET);
228 }
229 }
230 232
231 self->data_offset = lseek(fd, 0, SEEK_CUR); 233 self->data_offset = lseek(fd, 0, SEEK_CUR);
232 234
@@ -246,12 +248,10 @@ void perf_header__write(struct perf_header *self, int fd)
246 .offset = self->event_offset, 248 .offset = self->event_offset,
247 .size = self->event_size, 249 .size = self->event_size,
248 }, 250 },
249 .trace_info = {
250 .offset = self->trace_info_offset,
251 .size = self->trace_info_size,
252 },
253 }; 251 };
254 252
253 memcpy(&f_header.adds_features, &self->adds_features, sizeof(feat_mask_t));
254
255 lseek(fd, 0, SEEK_SET); 255 lseek(fd, 0, SEEK_SET);
256 do_write(fd, &f_header, sizeof(f_header)); 256 do_write(fd, &f_header, sizeof(f_header));
257 lseek(fd, self->data_offset + self->data_size, SEEK_SET); 257 lseek(fd, self->data_offset + self->data_size, SEEK_SET);
@@ -274,6 +274,20 @@ static void do_read(int fd, void *buf, size_t size)
274 } 274 }
275} 275}
276 276
277static void perf_header__adds_read(struct perf_header *self, int fd)
278{
279 const unsigned long *feat_mask = perf_header__adds_mask(self);
280
281 if (test_bit(HEADER_TRACE_INFO, feat_mask)) {
282 struct perf_file_section trace_sec;
283
284 do_read(fd, &trace_sec, sizeof(trace_sec));
285 lseek(fd, trace_sec.offset, SEEK_SET);
286 trace_report(fd);
287 lseek(fd, trace_sec.offset + trace_sec.size, SEEK_SET);
288 }
289};
290
277struct perf_header *perf_header__read(int fd) 291struct perf_header *perf_header__read(int fd)
278{ 292{
279 struct perf_header *self = perf_header__new(); 293 struct perf_header *self = perf_header__new();
@@ -292,9 +306,11 @@ struct perf_header *perf_header__read(int fd)
292 306
293 if (f_header.size != sizeof(f_header)) { 307 if (f_header.size != sizeof(f_header)) {
294 /* Support the previous format */ 308 /* Support the previous format */
295 if (f_header.size == offsetof(typeof(f_header), trace_info)) 309 if (f_header.size == offsetof(typeof(f_header), adds_features)) {
296 f_header.trace_info.size = 0; 310 unsigned long *mask = (unsigned long *)(void *)
297 else 311 &f_header.adds_features;
312 bitmap_zero(mask, HEADER_FEAT_BITS);
313 } else
298 die("incompatible file format"); 314 die("incompatible file format");
299 } 315 }
300 nr_attrs = f_header.attrs.size / sizeof(f_attr); 316 nr_attrs = f_header.attrs.size / sizeof(f_attr);
@@ -330,13 +346,9 @@ struct perf_header *perf_header__read(int fd)
330 event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type); 346 event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type);
331 } 347 }
332 348
333 self->trace_info_offset = f_header.trace_info.offset; 349 memcpy(&self->adds_features, &f_header.adds_features, sizeof(feat_mask_t));
334 self->trace_info_size = f_header.trace_info.size;
335 350
336 if (self->trace_info_size) { 351 perf_header__adds_read(self, fd);
337 lseek(fd, self->trace_info_offset, SEEK_SET);
338 trace_report(fd);
339 }
340 352
341 self->event_offset = f_header.event_types.offset; 353 self->event_offset = f_header.event_types.offset;
342 self->event_size = f_header.event_types.size; 354 self->event_size = f_header.event_types.size;
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 30aee5160dc0..0eb4a9126b7c 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -12,19 +12,29 @@ struct perf_header_attr {
12 off_t id_offset; 12 off_t id_offset;
13}; 13};
14 14
15#define HEADER_TRACE_INFO 1
16
17#define HEADER_FEAT_BITS 256
18
19typedef typeof(u64[HEADER_FEAT_BITS / 8]) feat_mask_t;
20
15struct perf_header { 21struct perf_header {
16 int frozen; 22 int frozen;
17 int attrs, size; 23 int attrs, size;
18 struct perf_header_attr **attr; 24 struct perf_header_attr **attr;
19 s64 attr_offset; 25 s64 attr_offset;
20 u64 data_offset; 26 u64 data_offset;
21 u64 data_size; 27 u64 data_size;
22 u64 event_offset; 28 u64 event_offset;
23 u64 event_size; 29 u64 event_size;
24 u64 trace_info_offset; 30 feat_mask_t adds_features;
25 u64 trace_info_size;
26}; 31};
27 32
33static inline unsigned long *perf_header__adds_mask(struct perf_header *self)
34{
35 return (unsigned long *)(void *)&self->adds_features;
36}
37
28struct perf_header *perf_header__read(int fd); 38struct perf_header *perf_header__read(int fd);
29void perf_header__write(struct perf_header *self, int fd); 39void perf_header__write(struct perf_header *self, int fd);
30 40
@@ -42,7 +52,7 @@ void perf_header_attr__add_id(struct perf_header_attr *self, u64 id);
42u64 perf_header__sample_type(struct perf_header *header); 52u64 perf_header__sample_type(struct perf_header *header);
43struct perf_event_attr * 53struct perf_event_attr *
44perf_header__find_attr(u64 id, struct perf_header *header); 54perf_header__find_attr(u64 id, struct perf_header *header);
45void perf_header__set_trace_info(void); 55void perf_header__feat_trace_info(struct perf_header *header);
46 56
47struct perf_header *perf_header__new(void); 57struct perf_header *perf_header__new(void);
48 58