diff options
Diffstat (limited to 'tools/perf/util/header.c')
-rw-r--r-- | tools/perf/util/header.c | 110 |
1 files changed, 75 insertions, 35 deletions
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 9709d38113b1..ebed4f44ed36 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -186,41 +186,58 @@ static void write_buildid_table(int fd, struct list_head *id_head) | |||
186 | } | 186 | } |
187 | 187 | ||
188 | static void | 188 | static void |
189 | perf_header__adds_write(struct perf_header *self, int fd, bool at_exit) | 189 | perf_header__adds_write(struct perf_header *self, int fd) |
190 | { | 190 | { |
191 | struct perf_file_section trace_sec; | 191 | LIST_HEAD(id_list); |
192 | u64 cur_offset = lseek(fd, 0, SEEK_CUR); | 192 | int nr_sections; |
193 | struct perf_file_section *feat_sec; | ||
194 | int sec_size; | ||
195 | u64 sec_start; | ||
196 | int idx = 0; | ||
197 | |||
198 | if (fetch_build_id_table(&id_list)) | ||
199 | perf_header__set_feat(self, HEADER_BUILD_ID); | ||
200 | |||
201 | nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS); | ||
202 | if (!nr_sections) | ||
203 | return; | ||
204 | |||
205 | feat_sec = calloc(sizeof(*feat_sec), nr_sections); | ||
206 | if (!feat_sec) | ||
207 | die("No memory"); | ||
208 | |||
209 | sec_size = sizeof(*feat_sec) * nr_sections; | ||
210 | |||
211 | sec_start = self->data_offset + self->data_size; | ||
212 | lseek(fd, sec_start + sec_size, SEEK_SET); | ||
193 | 213 | ||
194 | if (perf_header__has_feat(self, HEADER_TRACE_INFO)) { | 214 | if (perf_header__has_feat(self, HEADER_TRACE_INFO)) { |
215 | struct perf_file_section *trace_sec; | ||
216 | |||
217 | trace_sec = &feat_sec[idx++]; | ||
218 | |||
195 | /* Write trace info */ | 219 | /* Write trace info */ |
196 | trace_sec.offset = lseek(fd, sizeof(trace_sec), SEEK_CUR); | 220 | trace_sec->offset = lseek(fd, 0, SEEK_CUR); |
197 | read_tracing_data(fd, attrs, nr_counters); | 221 | read_tracing_data(fd, attrs, nr_counters); |
198 | trace_sec.size = lseek(fd, 0, SEEK_CUR) - trace_sec.offset; | 222 | trace_sec->size = lseek(fd, 0, SEEK_CUR) - trace_sec->offset; |
199 | |||
200 | /* Write trace info headers */ | ||
201 | lseek(fd, cur_offset, SEEK_SET); | ||
202 | do_write(fd, &trace_sec, sizeof(trace_sec)); | ||
203 | |||
204 | /* | ||
205 | * Update cur_offset. So that other (future) | ||
206 | * features can set their own infos in this place. But if we are | ||
207 | * the only feature, at least that seeks to the place the data | ||
208 | * should begin. | ||
209 | */ | ||
210 | cur_offset = lseek(fd, trace_sec.offset + trace_sec.size, SEEK_SET); | ||
211 | } | 223 | } |
212 | 224 | ||
213 | if (at_exit) { | ||
214 | LIST_HEAD(id_list); | ||
215 | 225 | ||
216 | if (fetch_build_id_table(&id_list)) { | 226 | if (perf_header__has_feat(self, HEADER_BUILD_ID)) { |
217 | lseek(fd, self->data_offset + self->data_size, SEEK_SET); | 227 | struct perf_file_section *buildid_sec; |
218 | perf_header__set_feat(self, HEADER_BUILD_ID); | 228 | |
219 | write_buildid_table(fd, &id_list); | 229 | buildid_sec = &feat_sec[idx++]; |
220 | lseek(fd, cur_offset, SEEK_SET); | 230 | |
221 | } | 231 | /* Write build-ids */ |
232 | buildid_sec->offset = lseek(fd, 0, SEEK_CUR); | ||
233 | write_buildid_table(fd, &id_list); | ||
234 | buildid_sec->size = lseek(fd, 0, SEEK_CUR) - buildid_sec->offset; | ||
222 | } | 235 | } |
223 | }; | 236 | |
237 | lseek(fd, sec_start, SEEK_SET); | ||
238 | do_write(fd, feat_sec, sec_size); | ||
239 | free(feat_sec); | ||
240 | } | ||
224 | 241 | ||
225 | void perf_header__write(struct perf_header *self, int fd, bool at_exit) | 242 | void perf_header__write(struct perf_header *self, int fd, bool at_exit) |
226 | { | 243 | { |
@@ -260,10 +277,11 @@ void perf_header__write(struct perf_header *self, int fd, bool at_exit) | |||
260 | if (events) | 277 | if (events) |
261 | do_write(fd, events, self->event_size); | 278 | do_write(fd, events, self->event_size); |
262 | 279 | ||
263 | perf_header__adds_write(self, fd, at_exit); | ||
264 | |||
265 | self->data_offset = lseek(fd, 0, SEEK_CUR); | 280 | self->data_offset = lseek(fd, 0, SEEK_CUR); |
266 | 281 | ||
282 | if (at_exit) | ||
283 | perf_header__adds_write(self, fd); | ||
284 | |||
267 | f_header = (struct perf_file_header){ | 285 | f_header = (struct perf_file_header){ |
268 | .magic = PERF_MAGIC, | 286 | .magic = PERF_MAGIC, |
269 | .size = sizeof(f_header), | 287 | .size = sizeof(f_header), |
@@ -308,22 +326,44 @@ static void do_read(int fd, void *buf, size_t size) | |||
308 | 326 | ||
309 | static void perf_header__adds_read(struct perf_header *self, int fd) | 327 | static void perf_header__adds_read(struct perf_header *self, int fd) |
310 | { | 328 | { |
329 | struct perf_file_section *feat_sec; | ||
330 | int nr_sections; | ||
331 | int sec_size; | ||
332 | int idx = 0; | ||
333 | |||
334 | |||
335 | nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS); | ||
336 | if (!nr_sections) | ||
337 | return; | ||
338 | |||
339 | feat_sec = calloc(sizeof(*feat_sec), nr_sections); | ||
340 | if (!feat_sec) | ||
341 | die("No memory"); | ||
342 | |||
343 | sec_size = sizeof(*feat_sec) * nr_sections; | ||
344 | |||
345 | lseek(fd, self->data_offset + self->data_size, SEEK_SET); | ||
346 | |||
347 | do_read(fd, feat_sec, sec_size); | ||
348 | |||
311 | if (perf_header__has_feat(self, HEADER_TRACE_INFO)) { | 349 | if (perf_header__has_feat(self, HEADER_TRACE_INFO)) { |
312 | struct perf_file_section trace_sec; | 350 | struct perf_file_section *trace_sec; |
313 | 351 | ||
314 | do_read(fd, &trace_sec, sizeof(trace_sec)); | 352 | trace_sec = &feat_sec[idx++]; |
315 | lseek(fd, trace_sec.offset, SEEK_SET); | 353 | lseek(fd, trace_sec->offset, SEEK_SET); |
316 | trace_report(fd); | 354 | trace_report(fd); |
317 | lseek(fd, trace_sec.offset + trace_sec.size, SEEK_SET); | ||
318 | } | 355 | } |
319 | 356 | ||
320 | if (perf_header__has_feat(self, HEADER_BUILD_ID)) { | 357 | if (perf_header__has_feat(self, HEADER_BUILD_ID)) { |
321 | struct stat input_stat; | 358 | struct perf_file_section *buildid_sec; |
322 | 359 | ||
323 | fstat(fd, &input_stat); | 360 | buildid_sec = &feat_sec[idx++]; |
324 | if (perf_header__read_build_ids(self, fd, input_stat.st_size)) | 361 | lseek(fd, buildid_sec->offset, SEEK_SET); |
362 | if (perf_header__read_build_ids(fd, buildid_sec->size)) | ||
325 | pr_debug("failed to read buildids, continuing...\n"); | 363 | pr_debug("failed to read buildids, continuing...\n"); |
326 | } | 364 | } |
365 | |||
366 | free(feat_sec); | ||
327 | }; | 367 | }; |
328 | 368 | ||
329 | struct perf_header *perf_header__read(int fd) | 369 | struct perf_header *perf_header__read(int fd) |