diff options
-rw-r--r-- | tools/perf/builtin-record.c | 37 | ||||
-rw-r--r-- | tools/perf/util/header.c | 7 | ||||
-rw-r--r-- | tools/perf/util/session.c | 64 | ||||
-rw-r--r-- | tools/perf/util/session.h | 3 | ||||
-rw-r--r-- | tools/perf/util/symbol.c | 13 | ||||
-rw-r--r-- | tools/perf/util/symbol.h | 2 |
6 files changed, 73 insertions, 53 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 949167efa1ed..706f00196b87 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
@@ -12,6 +12,7 @@ | |||
12 | 12 | ||
13 | #include "perf.h" | 13 | #include "perf.h" |
14 | 14 | ||
15 | #include "util/build-id.h" | ||
15 | #include "util/util.h" | 16 | #include "util/util.h" |
16 | #include "util/parse-options.h" | 17 | #include "util/parse-options.h" |
17 | #include "util/parse-events.h" | 18 | #include "util/parse-events.h" |
@@ -65,6 +66,7 @@ static int nr_poll = 0; | |||
65 | static int nr_cpu = 0; | 66 | static int nr_cpu = 0; |
66 | 67 | ||
67 | static int file_new = 1; | 68 | static int file_new = 1; |
69 | static off_t post_processing_offset; | ||
68 | 70 | ||
69 | static struct perf_session *session; | 71 | static struct perf_session *session; |
70 | 72 | ||
@@ -114,26 +116,10 @@ static void write_output(void *buf, size_t size) | |||
114 | } | 116 | } |
115 | } | 117 | } |
116 | 118 | ||
117 | static void write_event(event_t *buf, size_t size) | ||
118 | { | ||
119 | /* | ||
120 | * Add it to the list of DSOs, so that when we finish this | ||
121 | * record session we can pick the available build-ids. | ||
122 | */ | ||
123 | if (buf->header.type == PERF_RECORD_MMAP) { | ||
124 | struct list_head *head = &dsos__user; | ||
125 | if (buf->mmap.header.misc == 1) | ||
126 | head = &dsos__kernel; | ||
127 | __dsos__findnew(head, buf->mmap.filename); | ||
128 | } | ||
129 | |||
130 | write_output(buf, size); | ||
131 | } | ||
132 | |||
133 | static int process_synthesized_event(event_t *event, | 119 | static int process_synthesized_event(event_t *event, |
134 | struct perf_session *self __used) | 120 | struct perf_session *self __used) |
135 | { | 121 | { |
136 | write_event(event, event->header.size); | 122 | write_output(event, event->header.size); |
137 | return 0; | 123 | return 0; |
138 | } | 124 | } |
139 | 125 | ||
@@ -185,14 +171,14 @@ static void mmap_read(struct mmap_data *md) | |||
185 | size = md->mask + 1 - (old & md->mask); | 171 | size = md->mask + 1 - (old & md->mask); |
186 | old += size; | 172 | old += size; |
187 | 173 | ||
188 | write_event(buf, size); | 174 | write_output(buf, size); |
189 | } | 175 | } |
190 | 176 | ||
191 | buf = &data[old & md->mask]; | 177 | buf = &data[old & md->mask]; |
192 | size = head - old; | 178 | size = head - old; |
193 | old += size; | 179 | old += size; |
194 | 180 | ||
195 | write_event(buf, size); | 181 | write_output(buf, size); |
196 | 182 | ||
197 | md->prev = old; | 183 | md->prev = old; |
198 | mmap_write_tail(md, old); | 184 | mmap_write_tail(md, old); |
@@ -402,10 +388,21 @@ static void open_counters(int cpu, pid_t pid) | |||
402 | nr_cpu++; | 388 | nr_cpu++; |
403 | } | 389 | } |
404 | 390 | ||
391 | static int process_buildids(void) | ||
392 | { | ||
393 | u64 size = lseek(output, 0, SEEK_CUR); | ||
394 | |||
395 | session->fd = output; | ||
396 | return __perf_session__process_events(session, post_processing_offset, | ||
397 | size - post_processing_offset, | ||
398 | size, &build_id__mark_dso_hit_ops); | ||
399 | } | ||
400 | |||
405 | static void atexit_header(void) | 401 | static void atexit_header(void) |
406 | { | 402 | { |
407 | session->header.data_size += bytes_written; | 403 | session->header.data_size += bytes_written; |
408 | 404 | ||
405 | process_buildids(); | ||
409 | perf_header__write(&session->header, output, true); | 406 | perf_header__write(&session->header, output, true); |
410 | } | 407 | } |
411 | 408 | ||
@@ -558,6 +555,8 @@ static int __cmd_record(int argc, const char **argv) | |||
558 | return err; | 555 | return err; |
559 | } | 556 | } |
560 | 557 | ||
558 | post_processing_offset = lseek(output, 0, SEEK_CUR); | ||
559 | |||
561 | err = event__synthesize_kernel_mmap(process_synthesized_event, | 560 | err = event__synthesize_kernel_mmap(process_synthesized_event, |
562 | session, "_text"); | 561 | session, "_text"); |
563 | if (err < 0) { | 562 | if (err < 0) { |
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index ed3efd728b41..d5facd5ab1f7 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -205,8 +205,11 @@ static int __dsos__write_buildid_table(struct list_head *head, u16 misc, int fd) | |||
205 | dsos__for_each_with_build_id(pos, head) { | 205 | dsos__for_each_with_build_id(pos, head) { |
206 | int err; | 206 | int err; |
207 | struct build_id_event b; | 207 | struct build_id_event b; |
208 | size_t len = pos->long_name_len + 1; | 208 | size_t len; |
209 | 209 | ||
210 | if (!pos->hit) | ||
211 | continue; | ||
212 | len = pos->long_name_len + 1; | ||
210 | len = ALIGN(len, NAME_ALIGN); | 213 | len = ALIGN(len, NAME_ALIGN); |
211 | memset(&b, 0, sizeof(b)); | 214 | memset(&b, 0, sizeof(b)); |
212 | memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id)); | 215 | memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id)); |
@@ -371,7 +374,7 @@ static int perf_header__adds_write(struct perf_header *self, int fd) | |||
371 | u64 sec_start; | 374 | u64 sec_start; |
372 | int idx = 0, err; | 375 | int idx = 0, err; |
373 | 376 | ||
374 | if (dsos__read_build_ids()) | 377 | if (dsos__read_build_ids(true)) |
375 | perf_header__set_feat(self, HEADER_BUILD_ID); | 378 | perf_header__set_feat(self, HEADER_BUILD_ID); |
376 | 379 | ||
377 | nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS); | 380 | nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS); |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index aa8a03120bbd..74cbc64a3a3c 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
@@ -385,8 +385,9 @@ static struct thread *perf_session__register_idle_thread(struct perf_session *se | |||
385 | return thread; | 385 | return thread; |
386 | } | 386 | } |
387 | 387 | ||
388 | int perf_session__process_events(struct perf_session *self, | 388 | int __perf_session__process_events(struct perf_session *self, |
389 | struct perf_event_ops *ops) | 389 | u64 data_offset, u64 data_size, |
390 | u64 file_size, struct perf_event_ops *ops) | ||
390 | { | 391 | { |
391 | int err, mmap_prot, mmap_flags; | 392 | int err, mmap_prot, mmap_flags; |
392 | u64 head, shift; | 393 | u64 head, shift; |
@@ -396,32 +397,11 @@ int perf_session__process_events(struct perf_session *self, | |||
396 | uint32_t size; | 397 | uint32_t size; |
397 | char *buf; | 398 | char *buf; |
398 | 399 | ||
399 | if (perf_session__register_idle_thread(self) == NULL) | ||
400 | return -ENOMEM; | ||
401 | |||
402 | perf_event_ops__fill_defaults(ops); | 400 | perf_event_ops__fill_defaults(ops); |
403 | 401 | ||
404 | page_size = sysconf(_SC_PAGESIZE); | 402 | page_size = sysconf(_SC_PAGESIZE); |
405 | 403 | ||
406 | head = self->header.data_offset; | 404 | head = data_offset; |
407 | |||
408 | if (!symbol_conf.full_paths) { | ||
409 | char bf[PATH_MAX]; | ||
410 | |||
411 | if (getcwd(bf, sizeof(bf)) == NULL) { | ||
412 | err = -errno; | ||
413 | out_getcwd_err: | ||
414 | pr_err("failed to get the current directory\n"); | ||
415 | goto out_err; | ||
416 | } | ||
417 | self->cwd = strdup(bf); | ||
418 | if (self->cwd == NULL) { | ||
419 | err = -ENOMEM; | ||
420 | goto out_getcwd_err; | ||
421 | } | ||
422 | self->cwdlen = strlen(self->cwd); | ||
423 | } | ||
424 | |||
425 | shift = page_size * (head / page_size); | 405 | shift = page_size * (head / page_size); |
426 | offset += shift; | 406 | offset += shift; |
427 | head -= shift; | 407 | head -= shift; |
@@ -486,10 +466,10 @@ more: | |||
486 | 466 | ||
487 | head += size; | 467 | head += size; |
488 | 468 | ||
489 | if (offset + head >= self->header.data_offset + self->header.data_size) | 469 | if (offset + head >= data_offset + data_size) |
490 | goto done; | 470 | goto done; |
491 | 471 | ||
492 | if (offset + head < self->size) | 472 | if (offset + head < file_size) |
493 | goto more; | 473 | goto more; |
494 | done: | 474 | done: |
495 | err = 0; | 475 | err = 0; |
@@ -497,6 +477,38 @@ out_err: | |||
497 | return err; | 477 | return err; |
498 | } | 478 | } |
499 | 479 | ||
480 | int perf_session__process_events(struct perf_session *self, | ||
481 | struct perf_event_ops *ops) | ||
482 | { | ||
483 | int err; | ||
484 | |||
485 | if (perf_session__register_idle_thread(self) == NULL) | ||
486 | return -ENOMEM; | ||
487 | |||
488 | if (!symbol_conf.full_paths) { | ||
489 | char bf[PATH_MAX]; | ||
490 | |||
491 | if (getcwd(bf, sizeof(bf)) == NULL) { | ||
492 | err = -errno; | ||
493 | out_getcwd_err: | ||
494 | pr_err("failed to get the current directory\n"); | ||
495 | goto out_err; | ||
496 | } | ||
497 | self->cwd = strdup(bf); | ||
498 | if (self->cwd == NULL) { | ||
499 | err = -ENOMEM; | ||
500 | goto out_getcwd_err; | ||
501 | } | ||
502 | self->cwdlen = strlen(self->cwd); | ||
503 | } | ||
504 | |||
505 | err = __perf_session__process_events(self, self->header.data_offset, | ||
506 | self->header.data_size, | ||
507 | self->size, ops); | ||
508 | out_err: | ||
509 | return err; | ||
510 | } | ||
511 | |||
500 | bool perf_session__has_traces(struct perf_session *self, const char *msg) | 512 | bool perf_session__has_traces(struct perf_session *self, const char *msg) |
501 | { | 513 | { |
502 | if (!(self->sample_type & PERF_SAMPLE_RAW)) { | 514 | if (!(self->sample_type & PERF_SAMPLE_RAW)) { |
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 752d75aebade..31950fcd8a4d 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h | |||
@@ -50,6 +50,9 @@ void perf_session__delete(struct perf_session *self); | |||
50 | 50 | ||
51 | void perf_event_header__bswap(struct perf_event_header *self); | 51 | void perf_event_header__bswap(struct perf_event_header *self); |
52 | 52 | ||
53 | int __perf_session__process_events(struct perf_session *self, | ||
54 | u64 data_offset, u64 data_size, u64 size, | ||
55 | struct perf_event_ops *ops); | ||
53 | int perf_session__process_events(struct perf_session *self, | 56 | int perf_session__process_events(struct perf_session *self, |
54 | struct perf_event_ops *event_ops); | 57 | struct perf_event_ops *event_ops); |
55 | 58 | ||
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index e752837363ee..bfb055459670 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -1076,25 +1076,28 @@ static bool dso__build_id_equal(const struct dso *self, u8 *build_id) | |||
1076 | return memcmp(self->build_id, build_id, sizeof(self->build_id)) == 0; | 1076 | return memcmp(self->build_id, build_id, sizeof(self->build_id)) == 0; |
1077 | } | 1077 | } |
1078 | 1078 | ||
1079 | static bool __dsos__read_build_ids(struct list_head *head) | 1079 | static bool __dsos__read_build_ids(struct list_head *head, bool with_hits) |
1080 | { | 1080 | { |
1081 | bool have_build_id = false; | 1081 | bool have_build_id = false; |
1082 | struct dso *pos; | 1082 | struct dso *pos; |
1083 | 1083 | ||
1084 | list_for_each_entry(pos, head, node) | 1084 | list_for_each_entry(pos, head, node) { |
1085 | if (with_hits && !pos->hit) | ||
1086 | continue; | ||
1085 | if (filename__read_build_id(pos->long_name, pos->build_id, | 1087 | if (filename__read_build_id(pos->long_name, pos->build_id, |
1086 | sizeof(pos->build_id)) > 0) { | 1088 | sizeof(pos->build_id)) > 0) { |
1087 | have_build_id = true; | 1089 | have_build_id = true; |
1088 | pos->has_build_id = true; | 1090 | pos->has_build_id = true; |
1089 | } | 1091 | } |
1092 | } | ||
1090 | 1093 | ||
1091 | return have_build_id; | 1094 | return have_build_id; |
1092 | } | 1095 | } |
1093 | 1096 | ||
1094 | bool dsos__read_build_ids(void) | 1097 | bool dsos__read_build_ids(bool with_hits) |
1095 | { | 1098 | { |
1096 | bool kbuildids = __dsos__read_build_ids(&dsos__kernel), | 1099 | bool kbuildids = __dsos__read_build_ids(&dsos__kernel, with_hits), |
1097 | ubuildids = __dsos__read_build_ids(&dsos__user); | 1100 | ubuildids = __dsos__read_build_ids(&dsos__user, with_hits); |
1098 | return kbuildids || ubuildids; | 1101 | return kbuildids || ubuildids; |
1099 | } | 1102 | } |
1100 | 1103 | ||
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index e90568a9e467..1b4192ee5300 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
@@ -157,7 +157,7 @@ struct symbol *dso__find_symbol_by_name(struct dso *self, enum map_type type, | |||
157 | 157 | ||
158 | int filename__read_build_id(const char *filename, void *bf, size_t size); | 158 | int filename__read_build_id(const char *filename, void *bf, size_t size); |
159 | int sysfs__read_build_id(const char *filename, void *bf, size_t size); | 159 | int sysfs__read_build_id(const char *filename, void *bf, size_t size); |
160 | bool dsos__read_build_ids(void); | 160 | bool dsos__read_build_ids(bool with_hits); |
161 | int build_id__sprintf(const u8 *self, int len, char *bf); | 161 | int build_id__sprintf(const u8 *self, int len, char *bf); |
162 | int kallsyms__parse(const char *filename, void *arg, | 162 | int kallsyms__parse(const char *filename, void *arg, |
163 | int (*process_symbol)(void *arg, const char *name, | 163 | int (*process_symbol)(void *arg, const char *name, |