diff options
Diffstat (limited to 'tools/perf/util')
-rw-r--r-- | tools/perf/util/build-id.c | 1 | ||||
-rw-r--r-- | tools/perf/util/event.c | 56 | ||||
-rw-r--r-- | tools/perf/util/event.h | 19 | ||||
-rw-r--r-- | tools/perf/util/evlist.c | 21 | ||||
-rw-r--r-- | tools/perf/util/evsel.c | 16 | ||||
-rw-r--r-- | tools/perf/util/header.c | 3 | ||||
-rw-r--r-- | tools/perf/util/machine.c | 53 | ||||
-rw-r--r-- | tools/perf/util/machine.h | 1 | ||||
-rw-r--r-- | tools/perf/util/map.c | 8 | ||||
-rw-r--r-- | tools/perf/util/map.h | 8 | ||||
-rw-r--r-- | tools/perf/util/session.c | 68 | ||||
-rw-r--r-- | tools/perf/util/tool.h | 1 |
12 files changed, 198 insertions, 57 deletions
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index fb584092eb88..7ded71d19d75 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c | |||
@@ -67,6 +67,7 @@ static int perf_event__exit_del_thread(struct perf_tool *tool __maybe_unused, | |||
67 | struct perf_tool build_id__mark_dso_hit_ops = { | 67 | struct perf_tool build_id__mark_dso_hit_ops = { |
68 | .sample = build_id__mark_dso_hit, | 68 | .sample = build_id__mark_dso_hit, |
69 | .mmap = perf_event__process_mmap, | 69 | .mmap = perf_event__process_mmap, |
70 | .mmap2 = perf_event__process_mmap2, | ||
70 | .fork = perf_event__process_fork, | 71 | .fork = perf_event__process_fork, |
71 | .exit = perf_event__exit_del_thread, | 72 | .exit = perf_event__exit_del_thread, |
72 | .attr = perf_event__process_attr, | 73 | .attr = perf_event__process_attr, |
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 8d51f21107aa..9b393e7dca6f 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
@@ -11,6 +11,7 @@ | |||
11 | static const char *perf_event__names[] = { | 11 | static const char *perf_event__names[] = { |
12 | [0] = "TOTAL", | 12 | [0] = "TOTAL", |
13 | [PERF_RECORD_MMAP] = "MMAP", | 13 | [PERF_RECORD_MMAP] = "MMAP", |
14 | [PERF_RECORD_MMAP2] = "MMAP2", | ||
14 | [PERF_RECORD_LOST] = "LOST", | 15 | [PERF_RECORD_LOST] = "LOST", |
15 | [PERF_RECORD_COMM] = "COMM", | 16 | [PERF_RECORD_COMM] = "COMM", |
16 | [PERF_RECORD_EXIT] = "EXIT", | 17 | [PERF_RECORD_EXIT] = "EXIT", |
@@ -186,7 +187,7 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool, | |||
186 | return -1; | 187 | return -1; |
187 | } | 188 | } |
188 | 189 | ||
189 | event->header.type = PERF_RECORD_MMAP; | 190 | event->header.type = PERF_RECORD_MMAP2; |
190 | /* | 191 | /* |
191 | * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c | 192 | * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c |
192 | */ | 193 | */ |
@@ -197,7 +198,9 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool, | |||
197 | char prot[5]; | 198 | char prot[5]; |
198 | char execname[PATH_MAX]; | 199 | char execname[PATH_MAX]; |
199 | char anonstr[] = "//anon"; | 200 | char anonstr[] = "//anon"; |
201 | unsigned int ino; | ||
200 | size_t size; | 202 | size_t size; |
203 | ssize_t n; | ||
201 | 204 | ||
202 | if (fgets(bf, sizeof(bf), fp) == NULL) | 205 | if (fgets(bf, sizeof(bf), fp) == NULL) |
203 | break; | 206 | break; |
@@ -206,9 +209,16 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool, | |||
206 | strcpy(execname, ""); | 209 | strcpy(execname, ""); |
207 | 210 | ||
208 | /* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */ | 211 | /* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */ |
209 | sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %*x:%*x %*u %s\n", | 212 | n = sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %x:%x %u %s\n", |
210 | &event->mmap.start, &event->mmap.len, prot, | 213 | &event->mmap2.start, &event->mmap2.len, prot, |
211 | &event->mmap.pgoff, execname); | 214 | &event->mmap2.pgoff, &event->mmap2.maj, |
215 | &event->mmap2.min, | ||
216 | &ino, execname); | ||
217 | |||
218 | event->mmap2.ino = (u64)ino; | ||
219 | |||
220 | if (n != 8) | ||
221 | continue; | ||
212 | 222 | ||
213 | if (prot[2] != 'x') | 223 | if (prot[2] != 'x') |
214 | continue; | 224 | continue; |
@@ -217,15 +227,15 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool, | |||
217 | strcpy(execname, anonstr); | 227 | strcpy(execname, anonstr); |
218 | 228 | ||
219 | size = strlen(execname) + 1; | 229 | size = strlen(execname) + 1; |
220 | memcpy(event->mmap.filename, execname, size); | 230 | memcpy(event->mmap2.filename, execname, size); |
221 | size = PERF_ALIGN(size, sizeof(u64)); | 231 | size = PERF_ALIGN(size, sizeof(u64)); |
222 | event->mmap.len -= event->mmap.start; | 232 | event->mmap2.len -= event->mmap.start; |
223 | event->mmap.header.size = (sizeof(event->mmap) - | 233 | event->mmap2.header.size = (sizeof(event->mmap2) - |
224 | (sizeof(event->mmap.filename) - size)); | 234 | (sizeof(event->mmap2.filename) - size)); |
225 | memset(event->mmap.filename + size, 0, machine->id_hdr_size); | 235 | memset(event->mmap2.filename + size, 0, machine->id_hdr_size); |
226 | event->mmap.header.size += machine->id_hdr_size; | 236 | event->mmap2.header.size += machine->id_hdr_size; |
227 | event->mmap.pid = tgid; | 237 | event->mmap2.pid = tgid; |
228 | event->mmap.tid = pid; | 238 | event->mmap2.tid = pid; |
229 | 239 | ||
230 | if (process(tool, event, &synth_sample, machine) != 0) { | 240 | if (process(tool, event, &synth_sample, machine) != 0) { |
231 | rc = -1; | 241 | rc = -1; |
@@ -527,6 +537,17 @@ size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp) | |||
527 | event->mmap.len, event->mmap.pgoff, event->mmap.filename); | 537 | event->mmap.len, event->mmap.pgoff, event->mmap.filename); |
528 | } | 538 | } |
529 | 539 | ||
540 | size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp) | ||
541 | { | ||
542 | return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 | ||
543 | " %02x:%02x %"PRIu64" %"PRIu64"]: %s\n", | ||
544 | event->mmap2.pid, event->mmap2.tid, event->mmap2.start, | ||
545 | event->mmap2.len, event->mmap2.pgoff, event->mmap2.maj, | ||
546 | event->mmap2.min, event->mmap2.ino, | ||
547 | event->mmap2.ino_generation, | ||
548 | event->mmap2.filename); | ||
549 | } | ||
550 | |||
530 | int perf_event__process_mmap(struct perf_tool *tool __maybe_unused, | 551 | int perf_event__process_mmap(struct perf_tool *tool __maybe_unused, |
531 | union perf_event *event, | 552 | union perf_event *event, |
532 | struct perf_sample *sample __maybe_unused, | 553 | struct perf_sample *sample __maybe_unused, |
@@ -535,6 +556,14 @@ int perf_event__process_mmap(struct perf_tool *tool __maybe_unused, | |||
535 | return machine__process_mmap_event(machine, event); | 556 | return machine__process_mmap_event(machine, event); |
536 | } | 557 | } |
537 | 558 | ||
559 | int perf_event__process_mmap2(struct perf_tool *tool __maybe_unused, | ||
560 | union perf_event *event, | ||
561 | struct perf_sample *sample __maybe_unused, | ||
562 | struct machine *machine) | ||
563 | { | ||
564 | return machine__process_mmap2_event(machine, event); | ||
565 | } | ||
566 | |||
538 | size_t perf_event__fprintf_task(union perf_event *event, FILE *fp) | 567 | size_t perf_event__fprintf_task(union perf_event *event, FILE *fp) |
539 | { | 568 | { |
540 | return fprintf(fp, "(%d:%d):(%d:%d)\n", | 569 | return fprintf(fp, "(%d:%d):(%d:%d)\n", |
@@ -574,6 +603,9 @@ size_t perf_event__fprintf(union perf_event *event, FILE *fp) | |||
574 | case PERF_RECORD_MMAP: | 603 | case PERF_RECORD_MMAP: |
575 | ret += perf_event__fprintf_mmap(event, fp); | 604 | ret += perf_event__fprintf_mmap(event, fp); |
576 | break; | 605 | break; |
606 | case PERF_RECORD_MMAP2: | ||
607 | ret += perf_event__fprintf_mmap2(event, fp); | ||
608 | break; | ||
577 | default: | 609 | default: |
578 | ret += fprintf(fp, "\n"); | 610 | ret += fprintf(fp, "\n"); |
579 | } | 611 | } |
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 93130d856bf0..c67ecc457d29 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h | |||
@@ -17,6 +17,19 @@ struct mmap_event { | |||
17 | char filename[PATH_MAX]; | 17 | char filename[PATH_MAX]; |
18 | }; | 18 | }; |
19 | 19 | ||
20 | struct mmap2_event { | ||
21 | struct perf_event_header header; | ||
22 | u32 pid, tid; | ||
23 | u64 start; | ||
24 | u64 len; | ||
25 | u64 pgoff; | ||
26 | u32 maj; | ||
27 | u32 min; | ||
28 | u64 ino; | ||
29 | u64 ino_generation; | ||
30 | char filename[PATH_MAX]; | ||
31 | }; | ||
32 | |||
20 | struct comm_event { | 33 | struct comm_event { |
21 | struct perf_event_header header; | 34 | struct perf_event_header header; |
22 | u32 pid, tid; | 35 | u32 pid, tid; |
@@ -159,6 +172,7 @@ struct tracing_data_event { | |||
159 | union perf_event { | 172 | union perf_event { |
160 | struct perf_event_header header; | 173 | struct perf_event_header header; |
161 | struct mmap_event mmap; | 174 | struct mmap_event mmap; |
175 | struct mmap2_event mmap2; | ||
162 | struct comm_event comm; | 176 | struct comm_event comm; |
163 | struct fork_event fork; | 177 | struct fork_event fork; |
164 | struct lost_event lost; | 178 | struct lost_event lost; |
@@ -208,6 +222,10 @@ int perf_event__process_mmap(struct perf_tool *tool, | |||
208 | union perf_event *event, | 222 | union perf_event *event, |
209 | struct perf_sample *sample, | 223 | struct perf_sample *sample, |
210 | struct machine *machine); | 224 | struct machine *machine); |
225 | int perf_event__process_mmap2(struct perf_tool *tool, | ||
226 | union perf_event *event, | ||
227 | struct perf_sample *sample, | ||
228 | struct machine *machine); | ||
211 | int perf_event__process_fork(struct perf_tool *tool, | 229 | int perf_event__process_fork(struct perf_tool *tool, |
212 | union perf_event *event, | 230 | union perf_event *event, |
213 | struct perf_sample *sample, | 231 | struct perf_sample *sample, |
@@ -238,6 +256,7 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type, | |||
238 | 256 | ||
239 | size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp); | 257 | size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp); |
240 | size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp); | 258 | size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp); |
259 | size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp); | ||
241 | size_t perf_event__fprintf_task(union perf_event *event, FILE *fp); | 260 | size_t perf_event__fprintf_task(union perf_event *event, FILE *fp); |
242 | size_t perf_event__fprintf(union perf_event *event, FILE *fp); | 261 | size_t perf_event__fprintf(union perf_event *event, FILE *fp); |
243 | 262 | ||
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index b8727ae45e3b..f9f77bee0b1b 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c | |||
@@ -64,6 +64,16 @@ void perf_evlist__set_id_pos(struct perf_evlist *evlist) | |||
64 | evlist->is_pos = first->is_pos; | 64 | evlist->is_pos = first->is_pos; |
65 | } | 65 | } |
66 | 66 | ||
67 | static void perf_evlist__update_id_pos(struct perf_evlist *evlist) | ||
68 | { | ||
69 | struct perf_evsel *evsel; | ||
70 | |||
71 | list_for_each_entry(evsel, &evlist->entries, node) | ||
72 | perf_evsel__calc_id_pos(evsel); | ||
73 | |||
74 | perf_evlist__set_id_pos(evlist); | ||
75 | } | ||
76 | |||
67 | static void perf_evlist__purge(struct perf_evlist *evlist) | 77 | static void perf_evlist__purge(struct perf_evlist *evlist) |
68 | { | 78 | { |
69 | struct perf_evsel *pos, *n; | 79 | struct perf_evsel *pos, *n; |
@@ -446,20 +456,25 @@ static int perf_evlist__event2id(struct perf_evlist *evlist, | |||
446 | static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist, | 456 | static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist, |
447 | union perf_event *event) | 457 | union perf_event *event) |
448 | { | 458 | { |
459 | struct perf_evsel *first = perf_evlist__first(evlist); | ||
449 | struct hlist_head *head; | 460 | struct hlist_head *head; |
450 | struct perf_sample_id *sid; | 461 | struct perf_sample_id *sid; |
451 | int hash; | 462 | int hash; |
452 | u64 id; | 463 | u64 id; |
453 | 464 | ||
454 | if (evlist->nr_entries == 1) | 465 | if (evlist->nr_entries == 1) |
455 | return perf_evlist__first(evlist); | 466 | return first; |
467 | |||
468 | if (!first->attr.sample_id_all && | ||
469 | event->header.type != PERF_RECORD_SAMPLE) | ||
470 | return first; | ||
456 | 471 | ||
457 | if (perf_evlist__event2id(evlist, event, &id)) | 472 | if (perf_evlist__event2id(evlist, event, &id)) |
458 | return NULL; | 473 | return NULL; |
459 | 474 | ||
460 | /* Synthesized events have an id of zero */ | 475 | /* Synthesized events have an id of zero */ |
461 | if (!id) | 476 | if (!id) |
462 | return perf_evlist__first(evlist); | 477 | return first; |
463 | 478 | ||
464 | hash = hash_64(id, PERF_EVLIST__HLIST_BITS); | 479 | hash = hash_64(id, PERF_EVLIST__HLIST_BITS); |
465 | head = &evlist->heads[hash]; | 480 | head = &evlist->heads[hash]; |
@@ -915,6 +930,8 @@ int perf_evlist__open(struct perf_evlist *evlist) | |||
915 | struct perf_evsel *evsel; | 930 | struct perf_evsel *evsel; |
916 | int err; | 931 | int err; |
917 | 932 | ||
933 | perf_evlist__update_id_pos(evlist); | ||
934 | |||
918 | list_for_each_entry(evsel, &evlist->entries, node) { | 935 | list_for_each_entry(evsel, &evlist->entries, node) { |
919 | err = perf_evsel__open(evsel, evlist->cpus, evlist->threads); | 936 | err = perf_evsel__open(evsel, evlist->cpus, evlist->threads); |
920 | if (err < 0) | 937 | if (err < 0) |
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 3612183e2cc5..0ce9febf1ba0 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
@@ -27,6 +27,7 @@ | |||
27 | static struct { | 27 | static struct { |
28 | bool sample_id_all; | 28 | bool sample_id_all; |
29 | bool exclude_guest; | 29 | bool exclude_guest; |
30 | bool mmap2; | ||
30 | } perf_missing_features; | 31 | } perf_missing_features; |
31 | 32 | ||
32 | #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) | 33 | #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) |
@@ -676,8 +677,9 @@ void perf_evsel__config(struct perf_evsel *evsel, | |||
676 | if (opts->sample_weight) | 677 | if (opts->sample_weight) |
677 | attr->sample_type |= PERF_SAMPLE_WEIGHT; | 678 | attr->sample_type |= PERF_SAMPLE_WEIGHT; |
678 | 679 | ||
679 | attr->mmap = track; | 680 | attr->mmap = track; |
680 | attr->comm = track; | 681 | attr->mmap2 = track && !perf_missing_features.mmap2; |
682 | attr->comm = track; | ||
681 | 683 | ||
682 | /* | 684 | /* |
683 | * XXX see the function comment above | 685 | * XXX see the function comment above |
@@ -1016,6 +1018,8 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, | |||
1016 | } | 1018 | } |
1017 | 1019 | ||
1018 | fallback_missing_features: | 1020 | fallback_missing_features: |
1021 | if (perf_missing_features.mmap2) | ||
1022 | evsel->attr.mmap2 = 0; | ||
1019 | if (perf_missing_features.exclude_guest) | 1023 | if (perf_missing_features.exclude_guest) |
1020 | evsel->attr.exclude_guest = evsel->attr.exclude_host = 0; | 1024 | evsel->attr.exclude_guest = evsel->attr.exclude_host = 0; |
1021 | retry_sample_id: | 1025 | retry_sample_id: |
@@ -1080,8 +1084,11 @@ try_fallback: | |||
1080 | if (err != -EINVAL || cpu > 0 || thread > 0) | 1084 | if (err != -EINVAL || cpu > 0 || thread > 0) |
1081 | goto out_close; | 1085 | goto out_close; |
1082 | 1086 | ||
1083 | if (!perf_missing_features.exclude_guest && | 1087 | if (!perf_missing_features.mmap2 && evsel->attr.mmap2) { |
1084 | (evsel->attr.exclude_guest || evsel->attr.exclude_host)) { | 1088 | perf_missing_features.mmap2 = true; |
1089 | goto fallback_missing_features; | ||
1090 | } else if (!perf_missing_features.exclude_guest && | ||
1091 | (evsel->attr.exclude_guest || evsel->attr.exclude_host)) { | ||
1085 | perf_missing_features.exclude_guest = true; | 1092 | perf_missing_features.exclude_guest = true; |
1086 | goto fallback_missing_features; | 1093 | goto fallback_missing_features; |
1087 | } else if (!perf_missing_features.sample_id_all) { | 1094 | } else if (!perf_missing_features.sample_id_all) { |
@@ -1925,6 +1932,7 @@ int perf_evsel__fprintf(struct perf_evsel *evsel, | |||
1925 | if_print(exclude_hv); | 1932 | if_print(exclude_hv); |
1926 | if_print(exclude_idle); | 1933 | if_print(exclude_idle); |
1927 | if_print(mmap); | 1934 | if_print(mmap); |
1935 | if_print(mmap2); | ||
1928 | if_print(comm); | 1936 | if_print(comm); |
1929 | if_print(freq); | 1937 | if_print(freq); |
1930 | if_print(inherit_stat); | 1938 | if_print(inherit_stat); |
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index a33197a4fd21..26441d0e571b 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -1351,6 +1351,9 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp) | |||
1351 | 1351 | ||
1352 | fprintf(fp, ", precise_ip = %d", evsel->attr.precise_ip); | 1352 | fprintf(fp, ", precise_ip = %d", evsel->attr.precise_ip); |
1353 | 1353 | ||
1354 | fprintf(fp, ", attr_mmap2 = %d", evsel->attr.mmap2); | ||
1355 | fprintf(fp, ", attr_mmap = %d", evsel->attr.mmap); | ||
1356 | fprintf(fp, ", attr_mmap_data = %d", evsel->attr.mmap_data); | ||
1354 | if (evsel->ids) { | 1357 | if (evsel->ids) { |
1355 | fprintf(fp, ", id = {"); | 1358 | fprintf(fp, ", id = {"); |
1356 | for (j = 0, id = evsel->id; j < evsel->ids; j++, id++) { | 1359 | for (j = 0, id = evsel->id; j < evsel->ids; j++, id++) { |
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 1dca61f0512d..933d14f287ca 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c | |||
@@ -997,6 +997,54 @@ out_problem: | |||
997 | return -1; | 997 | return -1; |
998 | } | 998 | } |
999 | 999 | ||
1000 | int machine__process_mmap2_event(struct machine *machine, | ||
1001 | union perf_event *event) | ||
1002 | { | ||
1003 | u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | ||
1004 | struct thread *thread; | ||
1005 | struct map *map; | ||
1006 | enum map_type type; | ||
1007 | int ret = 0; | ||
1008 | |||
1009 | if (dump_trace) | ||
1010 | perf_event__fprintf_mmap2(event, stdout); | ||
1011 | |||
1012 | if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL || | ||
1013 | cpumode == PERF_RECORD_MISC_KERNEL) { | ||
1014 | ret = machine__process_kernel_mmap_event(machine, event); | ||
1015 | if (ret < 0) | ||
1016 | goto out_problem; | ||
1017 | return 0; | ||
1018 | } | ||
1019 | |||
1020 | thread = machine__findnew_thread(machine, event->mmap2.pid, | ||
1021 | event->mmap2.pid); | ||
1022 | if (thread == NULL) | ||
1023 | goto out_problem; | ||
1024 | |||
1025 | if (event->header.misc & PERF_RECORD_MISC_MMAP_DATA) | ||
1026 | type = MAP__VARIABLE; | ||
1027 | else | ||
1028 | type = MAP__FUNCTION; | ||
1029 | |||
1030 | map = map__new(&machine->user_dsos, event->mmap2.start, | ||
1031 | event->mmap2.len, event->mmap2.pgoff, | ||
1032 | event->mmap2.pid, event->mmap2.maj, | ||
1033 | event->mmap2.min, event->mmap2.ino, | ||
1034 | event->mmap2.ino_generation, | ||
1035 | event->mmap2.filename, type); | ||
1036 | |||
1037 | if (map == NULL) | ||
1038 | goto out_problem; | ||
1039 | |||
1040 | thread__insert_map(thread, map); | ||
1041 | return 0; | ||
1042 | |||
1043 | out_problem: | ||
1044 | dump_printf("problem processing PERF_RECORD_MMAP2, skipping event.\n"); | ||
1045 | return 0; | ||
1046 | } | ||
1047 | |||
1000 | int machine__process_mmap_event(struct machine *machine, union perf_event *event) | 1048 | int machine__process_mmap_event(struct machine *machine, union perf_event *event) |
1001 | { | 1049 | { |
1002 | u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | 1050 | u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; |
@@ -1028,7 +1076,8 @@ int machine__process_mmap_event(struct machine *machine, union perf_event *event | |||
1028 | 1076 | ||
1029 | map = map__new(&machine->user_dsos, event->mmap.start, | 1077 | map = map__new(&machine->user_dsos, event->mmap.start, |
1030 | event->mmap.len, event->mmap.pgoff, | 1078 | event->mmap.len, event->mmap.pgoff, |
1031 | event->mmap.pid, event->mmap.filename, | 1079 | event->mmap.pid, 0, 0, 0, 0, |
1080 | event->mmap.filename, | ||
1032 | type); | 1081 | type); |
1033 | 1082 | ||
1034 | if (map == NULL) | 1083 | if (map == NULL) |
@@ -1101,6 +1150,8 @@ int machine__process_event(struct machine *machine, union perf_event *event) | |||
1101 | ret = machine__process_comm_event(machine, event); break; | 1150 | ret = machine__process_comm_event(machine, event); break; |
1102 | case PERF_RECORD_MMAP: | 1151 | case PERF_RECORD_MMAP: |
1103 | ret = machine__process_mmap_event(machine, event); break; | 1152 | ret = machine__process_mmap_event(machine, event); break; |
1153 | case PERF_RECORD_MMAP2: | ||
1154 | ret = machine__process_mmap2_event(machine, event); break; | ||
1104 | case PERF_RECORD_FORK: | 1155 | case PERF_RECORD_FORK: |
1105 | ret = machine__process_fork_event(machine, event); break; | 1156 | ret = machine__process_fork_event(machine, event); break; |
1106 | case PERF_RECORD_EXIT: | 1157 | case PERF_RECORD_EXIT: |
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h index 0df925ba6a44..58a6be1fc739 100644 --- a/tools/perf/util/machine.h +++ b/tools/perf/util/machine.h | |||
@@ -45,6 +45,7 @@ int machine__process_exit_event(struct machine *machine, union perf_event *event | |||
45 | int machine__process_fork_event(struct machine *machine, union perf_event *event); | 45 | int machine__process_fork_event(struct machine *machine, union perf_event *event); |
46 | int machine__process_lost_event(struct machine *machine, union perf_event *event); | 46 | int machine__process_lost_event(struct machine *machine, union perf_event *event); |
47 | int machine__process_mmap_event(struct machine *machine, union perf_event *event); | 47 | int machine__process_mmap_event(struct machine *machine, union perf_event *event); |
48 | int machine__process_mmap2_event(struct machine *machine, union perf_event *event); | ||
48 | int machine__process_event(struct machine *machine, union perf_event *event); | 49 | int machine__process_event(struct machine *machine, union perf_event *event); |
49 | 50 | ||
50 | typedef void (*machine__process_t)(struct machine *machine, void *data); | 51 | typedef void (*machine__process_t)(struct machine *machine, void *data); |
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 9e8304ca343e..4f6680d2043b 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c | |||
@@ -48,7 +48,8 @@ void map__init(struct map *map, enum map_type type, | |||
48 | } | 48 | } |
49 | 49 | ||
50 | struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, | 50 | struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, |
51 | u64 pgoff, u32 pid, char *filename, | 51 | u64 pgoff, u32 pid, u32 d_maj, u32 d_min, u64 ino, |
52 | u64 ino_gen, char *filename, | ||
52 | enum map_type type) | 53 | enum map_type type) |
53 | { | 54 | { |
54 | struct map *map = malloc(sizeof(*map)); | 55 | struct map *map = malloc(sizeof(*map)); |
@@ -62,6 +63,11 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, | |||
62 | vdso = is_vdso_map(filename); | 63 | vdso = is_vdso_map(filename); |
63 | no_dso = is_no_dso_memory(filename); | 64 | no_dso = is_no_dso_memory(filename); |
64 | 65 | ||
66 | map->maj = d_maj; | ||
67 | map->min = d_min; | ||
68 | map->ino = ino; | ||
69 | map->ino_generation = ino_gen; | ||
70 | |||
65 | if (anon) { | 71 | if (anon) { |
66 | snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", pid); | 72 | snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", pid); |
67 | filename = newfilename; | 73 | filename = newfilename; |
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index 2cc93cbf0e17..4886ca280536 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h | |||
@@ -36,6 +36,9 @@ struct map { | |||
36 | bool erange_warned; | 36 | bool erange_warned; |
37 | u32 priv; | 37 | u32 priv; |
38 | u64 pgoff; | 38 | u64 pgoff; |
39 | u32 maj, min; /* only valid for MMAP2 record */ | ||
40 | u64 ino; /* only valid for MMAP2 record */ | ||
41 | u64 ino_generation;/* only valid for MMAP2 record */ | ||
39 | 42 | ||
40 | /* ip -> dso rip */ | 43 | /* ip -> dso rip */ |
41 | u64 (*map_ip)(struct map *, u64); | 44 | u64 (*map_ip)(struct map *, u64); |
@@ -88,8 +91,9 @@ typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym); | |||
88 | void map__init(struct map *map, enum map_type type, | 91 | void map__init(struct map *map, enum map_type type, |
89 | u64 start, u64 end, u64 pgoff, struct dso *dso); | 92 | u64 start, u64 end, u64 pgoff, struct dso *dso); |
90 | struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, | 93 | struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, |
91 | u64 pgoff, u32 pid, char *filename, | 94 | u64 pgoff, u32 pid, u32 d_maj, u32 d_min, u64 ino, |
92 | enum map_type type); | 95 | u64 ino_gen, |
96 | char *filename, enum map_type type); | ||
93 | struct map *map__new2(u64 start, struct dso *dso, enum map_type type); | 97 | struct map *map__new2(u64 start, struct dso *dso, enum map_type type); |
94 | void map__delete(struct map *map); | 98 | void map__delete(struct map *map); |
95 | struct map *map__clone(struct map *map); | 99 | struct map *map__clone(struct map *map); |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 1fc0c628683e..51f5edf2a6d0 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
@@ -351,6 +351,25 @@ static void perf_event__mmap_swap(union perf_event *event, | |||
351 | } | 351 | } |
352 | } | 352 | } |
353 | 353 | ||
354 | static void perf_event__mmap2_swap(union perf_event *event, | ||
355 | bool sample_id_all) | ||
356 | { | ||
357 | event->mmap2.pid = bswap_32(event->mmap2.pid); | ||
358 | event->mmap2.tid = bswap_32(event->mmap2.tid); | ||
359 | event->mmap2.start = bswap_64(event->mmap2.start); | ||
360 | event->mmap2.len = bswap_64(event->mmap2.len); | ||
361 | event->mmap2.pgoff = bswap_64(event->mmap2.pgoff); | ||
362 | event->mmap2.maj = bswap_32(event->mmap2.maj); | ||
363 | event->mmap2.min = bswap_32(event->mmap2.min); | ||
364 | event->mmap2.ino = bswap_64(event->mmap2.ino); | ||
365 | |||
366 | if (sample_id_all) { | ||
367 | void *data = &event->mmap2.filename; | ||
368 | |||
369 | data += PERF_ALIGN(strlen(data) + 1, sizeof(u64)); | ||
370 | swap_sample_id_all(event, data); | ||
371 | } | ||
372 | } | ||
354 | static void perf_event__task_swap(union perf_event *event, bool sample_id_all) | 373 | static void perf_event__task_swap(union perf_event *event, bool sample_id_all) |
355 | { | 374 | { |
356 | event->fork.pid = bswap_32(event->fork.pid); | 375 | event->fork.pid = bswap_32(event->fork.pid); |
@@ -455,6 +474,7 @@ typedef void (*perf_event__swap_op)(union perf_event *event, | |||
455 | 474 | ||
456 | static perf_event__swap_op perf_event__swap_ops[] = { | 475 | static perf_event__swap_op perf_event__swap_ops[] = { |
457 | [PERF_RECORD_MMAP] = perf_event__mmap_swap, | 476 | [PERF_RECORD_MMAP] = perf_event__mmap_swap, |
477 | [PERF_RECORD_MMAP2] = perf_event__mmap2_swap, | ||
458 | [PERF_RECORD_COMM] = perf_event__comm_swap, | 478 | [PERF_RECORD_COMM] = perf_event__comm_swap, |
459 | [PERF_RECORD_FORK] = perf_event__task_swap, | 479 | [PERF_RECORD_FORK] = perf_event__task_swap, |
460 | [PERF_RECORD_EXIT] = perf_event__task_swap, | 480 | [PERF_RECORD_EXIT] = perf_event__task_swap, |
@@ -504,6 +524,7 @@ static int flush_sample_queue(struct perf_session *s, | |||
504 | u64 limit = os->next_flush; | 524 | u64 limit = os->next_flush; |
505 | u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL; | 525 | u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL; |
506 | unsigned idx = 0, progress_next = os->nr_samples / 16; | 526 | unsigned idx = 0, progress_next = os->nr_samples / 16; |
527 | bool show_progress = limit == ULLONG_MAX; | ||
507 | int ret; | 528 | int ret; |
508 | 529 | ||
509 | if (!tool->ordered_samples || !limit) | 530 | if (!tool->ordered_samples || !limit) |
@@ -526,7 +547,7 @@ static int flush_sample_queue(struct perf_session *s, | |||
526 | os->last_flush = iter->timestamp; | 547 | os->last_flush = iter->timestamp; |
527 | list_del(&iter->list); | 548 | list_del(&iter->list); |
528 | list_add(&iter->list, &os->sample_cache); | 549 | list_add(&iter->list, &os->sample_cache); |
529 | if (++idx >= progress_next) { | 550 | if (show_progress && (++idx >= progress_next)) { |
530 | progress_next += os->nr_samples / 16; | 551 | progress_next += os->nr_samples / 16; |
531 | ui_progress__update(idx, os->nr_samples, | 552 | ui_progress__update(idx, os->nr_samples, |
532 | "Processing time ordered events..."); | 553 | "Processing time ordered events..."); |
@@ -850,7 +871,8 @@ static struct machine * | |||
850 | (cpumode == PERF_RECORD_MISC_GUEST_USER))) { | 871 | (cpumode == PERF_RECORD_MISC_GUEST_USER))) { |
851 | u32 pid; | 872 | u32 pid; |
852 | 873 | ||
853 | if (event->header.type == PERF_RECORD_MMAP) | 874 | if (event->header.type == PERF_RECORD_MMAP |
875 | || event->header.type == PERF_RECORD_MMAP2) | ||
854 | pid = event->mmap.pid; | 876 | pid = event->mmap.pid; |
855 | else | 877 | else |
856 | pid = sample->pid; | 878 | pid = sample->pid; |
@@ -977,6 +999,8 @@ static int perf_session_deliver_event(struct perf_session *session, | |||
977 | sample, evsel, machine); | 999 | sample, evsel, machine); |
978 | case PERF_RECORD_MMAP: | 1000 | case PERF_RECORD_MMAP: |
979 | return tool->mmap(tool, event, sample, machine); | 1001 | return tool->mmap(tool, event, sample, machine); |
1002 | case PERF_RECORD_MMAP2: | ||
1003 | return tool->mmap2(tool, event, sample, machine); | ||
980 | case PERF_RECORD_COMM: | 1004 | case PERF_RECORD_COMM: |
981 | return tool->comm(tool, event, sample, machine); | 1005 | return tool->comm(tool, event, sample, machine); |
982 | case PERF_RECORD_FORK: | 1006 | case PERF_RECORD_FORK: |
@@ -1619,52 +1643,26 @@ int __perf_session__set_tracepoints_handlers(struct perf_session *session, | |||
1619 | const struct perf_evsel_str_handler *assocs, | 1643 | const struct perf_evsel_str_handler *assocs, |
1620 | size_t nr_assocs) | 1644 | size_t nr_assocs) |
1621 | { | 1645 | { |
1622 | struct perf_evlist *evlist = session->evlist; | ||
1623 | struct event_format *format; | ||
1624 | struct perf_evsel *evsel; | 1646 | struct perf_evsel *evsel; |
1625 | char *tracepoint, *name; | ||
1626 | size_t i; | 1647 | size_t i; |
1627 | int err; | 1648 | int err; |
1628 | 1649 | ||
1629 | for (i = 0; i < nr_assocs; i++) { | 1650 | for (i = 0; i < nr_assocs; i++) { |
1630 | err = -ENOMEM; | 1651 | /* |
1631 | tracepoint = strdup(assocs[i].name); | 1652 | * Adding a handler for an event not in the session, |
1632 | if (tracepoint == NULL) | 1653 | * just ignore it. |
1633 | goto out; | 1654 | */ |
1634 | 1655 | evsel = perf_evlist__find_tracepoint_by_name(session->evlist, assocs[i].name); | |
1635 | err = -ENOENT; | ||
1636 | name = strchr(tracepoint, ':'); | ||
1637 | if (name == NULL) | ||
1638 | goto out_free; | ||
1639 | |||
1640 | *name++ = '\0'; | ||
1641 | format = pevent_find_event_by_name(session->pevent, | ||
1642 | tracepoint, name); | ||
1643 | if (format == NULL) { | ||
1644 | /* | ||
1645 | * Adding a handler for an event not in the session, | ||
1646 | * just ignore it. | ||
1647 | */ | ||
1648 | goto next; | ||
1649 | } | ||
1650 | |||
1651 | evsel = perf_evlist__find_tracepoint_by_id(evlist, format->id); | ||
1652 | if (evsel == NULL) | 1656 | if (evsel == NULL) |
1653 | goto next; | 1657 | continue; |
1654 | 1658 | ||
1655 | err = -EEXIST; | 1659 | err = -EEXIST; |
1656 | if (evsel->handler.func != NULL) | 1660 | if (evsel->handler.func != NULL) |
1657 | goto out_free; | 1661 | goto out; |
1658 | evsel->handler.func = assocs[i].handler; | 1662 | evsel->handler.func = assocs[i].handler; |
1659 | next: | ||
1660 | free(tracepoint); | ||
1661 | } | 1663 | } |
1662 | 1664 | ||
1663 | err = 0; | 1665 | err = 0; |
1664 | out: | 1666 | out: |
1665 | return err; | 1667 | return err; |
1666 | |||
1667 | out_free: | ||
1668 | free(tracepoint); | ||
1669 | goto out; | ||
1670 | } | 1668 | } |
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h index 62b16b6165ba..4385816d3d49 100644 --- a/tools/perf/util/tool.h +++ b/tools/perf/util/tool.h | |||
@@ -29,6 +29,7 @@ struct perf_tool { | |||
29 | event_sample sample, | 29 | event_sample sample, |
30 | read; | 30 | read; |
31 | event_op mmap, | 31 | event_op mmap, |
32 | mmap2, | ||
32 | comm, | 33 | comm, |
33 | fork, | 34 | fork, |
34 | exit, | 35 | exit, |