diff options
Diffstat (limited to 'tools/perf/util/header.c')
-rw-r--r-- | tools/perf/util/header.c | 74 |
1 files changed, 65 insertions, 9 deletions
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index e306857b2c2b..7d26659b806c 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -5,6 +5,8 @@ | |||
5 | 5 | ||
6 | #include "util.h" | 6 | #include "util.h" |
7 | #include "header.h" | 7 | #include "header.h" |
8 | #include "../perf.h" | ||
9 | #include "trace-event.h" | ||
8 | 10 | ||
9 | /* | 11 | /* |
10 | * Create new perf.data header attribute: | 12 | * Create new perf.data header attribute: |
@@ -46,23 +48,17 @@ void perf_header_attr__add_id(struct perf_header_attr *self, u64 id) | |||
46 | */ | 48 | */ |
47 | struct perf_header *perf_header__new(void) | 49 | struct perf_header *perf_header__new(void) |
48 | { | 50 | { |
49 | struct perf_header *self = malloc(sizeof(*self)); | 51 | struct perf_header *self = calloc(sizeof(*self), 1); |
50 | 52 | ||
51 | if (!self) | 53 | if (!self) |
52 | die("nomem"); | 54 | die("nomem"); |
53 | 55 | ||
54 | self->frozen = 0; | ||
55 | |||
56 | self->attrs = 0; | ||
57 | self->size = 1; | 56 | self->size = 1; |
58 | self->attr = malloc(sizeof(void *)); | 57 | self->attr = malloc(sizeof(void *)); |
59 | 58 | ||
60 | if (!self->attr) | 59 | if (!self->attr) |
61 | die("nomem"); | 60 | die("nomem"); |
62 | 61 | ||
63 | self->data_offset = 0; | ||
64 | self->data_size = 0; | ||
65 | |||
66 | return self; | 62 | return self; |
67 | } | 63 | } |
68 | 64 | ||
@@ -97,7 +93,7 @@ static struct perf_trace_event_type *events; | |||
97 | void perf_header__push_event(u64 id, const char *name) | 93 | void perf_header__push_event(u64 id, const char *name) |
98 | { | 94 | { |
99 | if (strlen(name) > MAX_EVENT_NAME) | 95 | if (strlen(name) > MAX_EVENT_NAME) |
100 | printf("Event %s will be truncated\n", name); | 96 | pr_warning("Event %s will be truncated\n", name); |
101 | 97 | ||
102 | if (!events) { | 98 | if (!events) { |
103 | events = malloc(sizeof(struct perf_trace_event_type)); | 99 | events = malloc(sizeof(struct perf_trace_event_type)); |
@@ -145,8 +141,14 @@ struct perf_file_header { | |||
145 | struct perf_file_section attrs; | 141 | struct perf_file_section attrs; |
146 | struct perf_file_section data; | 142 | struct perf_file_section data; |
147 | struct perf_file_section event_types; | 143 | struct perf_file_section event_types; |
144 | DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS); | ||
148 | }; | 145 | }; |
149 | 146 | ||
147 | void perf_header__feat_trace_info(struct perf_header *header) | ||
148 | { | ||
149 | set_bit(HEADER_TRACE_INFO, header->adds_features); | ||
150 | } | ||
151 | |||
150 | static void do_write(int fd, void *buf, size_t size) | 152 | static void do_write(int fd, void *buf, size_t size) |
151 | { | 153 | { |
152 | while (size) { | 154 | while (size) { |
@@ -160,6 +162,32 @@ static void do_write(int fd, void *buf, size_t size) | |||
160 | } | 162 | } |
161 | } | 163 | } |
162 | 164 | ||
165 | static void perf_header__adds_write(struct perf_header *self, int fd) | ||
166 | { | ||
167 | struct perf_file_section trace_sec; | ||
168 | u64 cur_offset = lseek(fd, 0, SEEK_CUR); | ||
169 | unsigned long *feat_mask = self->adds_features; | ||
170 | |||
171 | if (test_bit(HEADER_TRACE_INFO, feat_mask)) { | ||
172 | /* Write trace info */ | ||
173 | trace_sec.offset = lseek(fd, sizeof(trace_sec), SEEK_CUR); | ||
174 | read_tracing_data(fd, attrs, nr_counters); | ||
175 | trace_sec.size = lseek(fd, 0, SEEK_CUR) - trace_sec.offset; | ||
176 | |||
177 | /* Write trace info headers */ | ||
178 | lseek(fd, cur_offset, SEEK_SET); | ||
179 | do_write(fd, &trace_sec, sizeof(trace_sec)); | ||
180 | |||
181 | /* | ||
182 | * Update cur_offset. So that other (future) | ||
183 | * features can set their own infos in this place. But if we are | ||
184 | * the only feature, at least that seeks to the place the data | ||
185 | * should begin. | ||
186 | */ | ||
187 | cur_offset = lseek(fd, trace_sec.offset + trace_sec.size, SEEK_SET); | ||
188 | } | ||
189 | }; | ||
190 | |||
163 | void perf_header__write(struct perf_header *self, int fd) | 191 | void perf_header__write(struct perf_header *self, int fd) |
164 | { | 192 | { |
165 | struct perf_file_header f_header; | 193 | struct perf_file_header f_header; |
@@ -198,6 +226,7 @@ void perf_header__write(struct perf_header *self, int fd) | |||
198 | if (events) | 226 | if (events) |
199 | do_write(fd, events, self->event_size); | 227 | do_write(fd, events, self->event_size); |
200 | 228 | ||
229 | perf_header__adds_write(self, fd); | ||
201 | 230 | ||
202 | self->data_offset = lseek(fd, 0, SEEK_CUR); | 231 | self->data_offset = lseek(fd, 0, SEEK_CUR); |
203 | 232 | ||
@@ -219,6 +248,8 @@ void perf_header__write(struct perf_header *self, int fd) | |||
219 | }, | 248 | }, |
220 | }; | 249 | }; |
221 | 250 | ||
251 | memcpy(&f_header.adds_features, &self->adds_features, sizeof(self->adds_features)); | ||
252 | |||
222 | lseek(fd, 0, SEEK_SET); | 253 | lseek(fd, 0, SEEK_SET); |
223 | do_write(fd, &f_header, sizeof(f_header)); | 254 | do_write(fd, &f_header, sizeof(f_header)); |
224 | lseek(fd, self->data_offset + self->data_size, SEEK_SET); | 255 | lseek(fd, self->data_offset + self->data_size, SEEK_SET); |
@@ -241,6 +272,20 @@ static void do_read(int fd, void *buf, size_t size) | |||
241 | } | 272 | } |
242 | } | 273 | } |
243 | 274 | ||
275 | static void perf_header__adds_read(struct perf_header *self, int fd) | ||
276 | { | ||
277 | const unsigned long *feat_mask = self->adds_features; | ||
278 | |||
279 | if (test_bit(HEADER_TRACE_INFO, feat_mask)) { | ||
280 | struct perf_file_section trace_sec; | ||
281 | |||
282 | do_read(fd, &trace_sec, sizeof(trace_sec)); | ||
283 | lseek(fd, trace_sec.offset, SEEK_SET); | ||
284 | trace_report(fd); | ||
285 | lseek(fd, trace_sec.offset + trace_sec.size, SEEK_SET); | ||
286 | } | ||
287 | }; | ||
288 | |||
244 | struct perf_header *perf_header__read(int fd) | 289 | struct perf_header *perf_header__read(int fd) |
245 | { | 290 | { |
246 | struct perf_header *self = perf_header__new(); | 291 | struct perf_header *self = perf_header__new(); |
@@ -254,10 +299,16 @@ struct perf_header *perf_header__read(int fd) | |||
254 | do_read(fd, &f_header, sizeof(f_header)); | 299 | do_read(fd, &f_header, sizeof(f_header)); |
255 | 300 | ||
256 | if (f_header.magic != PERF_MAGIC || | 301 | if (f_header.magic != PERF_MAGIC || |
257 | f_header.size != sizeof(f_header) || | ||
258 | f_header.attr_size != sizeof(f_attr)) | 302 | f_header.attr_size != sizeof(f_attr)) |
259 | die("incompatible file format"); | 303 | die("incompatible file format"); |
260 | 304 | ||
305 | if (f_header.size != sizeof(f_header)) { | ||
306 | /* Support the previous format */ | ||
307 | if (f_header.size == offsetof(typeof(f_header), adds_features)) | ||
308 | bitmap_zero(f_header.adds_features, HEADER_FEAT_BITS); | ||
309 | else | ||
310 | die("incompatible file format"); | ||
311 | } | ||
261 | nr_attrs = f_header.attrs.size / sizeof(f_attr); | 312 | nr_attrs = f_header.attrs.size / sizeof(f_attr); |
262 | lseek(fd, f_header.attrs.offset, SEEK_SET); | 313 | lseek(fd, f_header.attrs.offset, SEEK_SET); |
263 | 314 | ||
@@ -290,6 +341,11 @@ struct perf_header *perf_header__read(int fd) | |||
290 | do_read(fd, events, f_header.event_types.size); | 341 | do_read(fd, events, f_header.event_types.size); |
291 | event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type); | 342 | event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type); |
292 | } | 343 | } |
344 | |||
345 | memcpy(&self->adds_features, &f_header.adds_features, sizeof(f_header.adds_features)); | ||
346 | |||
347 | perf_header__adds_read(self, fd); | ||
348 | |||
293 | self->event_offset = f_header.event_types.offset; | 349 | self->event_offset = f_header.event_types.offset; |
294 | self->event_size = f_header.event_types.size; | 350 | self->event_size = f_header.event_types.size; |
295 | 351 | ||