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) |
