diff options
Diffstat (limited to 'tools/perf/util/session.c')
| -rw-r--r-- | tools/perf/util/session.c | 141 |
1 files changed, 138 insertions, 3 deletions
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 6702ac28754b..f4478ce72fdb 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
| @@ -228,6 +228,15 @@ static int process_finished_round(struct perf_tool *tool, | |||
| 228 | union perf_event *event, | 228 | union perf_event *event, |
| 229 | struct perf_session *session); | 229 | struct perf_session *session); |
| 230 | 230 | ||
| 231 | static int process_id_index_stub(struct perf_tool *tool __maybe_unused, | ||
| 232 | union perf_event *event __maybe_unused, | ||
| 233 | struct perf_session *perf_session | ||
| 234 | __maybe_unused) | ||
| 235 | { | ||
| 236 | dump_printf(": unhandled!\n"); | ||
| 237 | return 0; | ||
| 238 | } | ||
| 239 | |||
| 231 | void perf_tool__fill_defaults(struct perf_tool *tool) | 240 | void perf_tool__fill_defaults(struct perf_tool *tool) |
| 232 | { | 241 | { |
| 233 | if (tool->sample == NULL) | 242 | if (tool->sample == NULL) |
| @@ -262,6 +271,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool) | |||
| 262 | else | 271 | else |
| 263 | tool->finished_round = process_finished_round_stub; | 272 | tool->finished_round = process_finished_round_stub; |
| 264 | } | 273 | } |
| 274 | if (tool->id_index == NULL) | ||
| 275 | tool->id_index = process_id_index_stub; | ||
| 265 | } | 276 | } |
| 266 | 277 | ||
| 267 | static void swap_sample_id_all(union perf_event *event, void *data) | 278 | static void swap_sample_id_all(union perf_event *event, void *data) |
| @@ -460,6 +471,7 @@ static perf_event__swap_op perf_event__swap_ops[] = { | |||
| 460 | [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap, | 471 | [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap, |
| 461 | [PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap, | 472 | [PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap, |
| 462 | [PERF_RECORD_HEADER_BUILD_ID] = NULL, | 473 | [PERF_RECORD_HEADER_BUILD_ID] = NULL, |
| 474 | [PERF_RECORD_ID_INDEX] = perf_event__all64_swap, | ||
| 463 | [PERF_RECORD_HEADER_MAX] = NULL, | 475 | [PERF_RECORD_HEADER_MAX] = NULL, |
| 464 | }; | 476 | }; |
| 465 | 477 | ||
| @@ -888,11 +900,26 @@ static s64 perf_session__process_user_event(struct perf_session *session, | |||
| 888 | return tool->build_id(tool, event, session); | 900 | return tool->build_id(tool, event, session); |
| 889 | case PERF_RECORD_FINISHED_ROUND: | 901 | case PERF_RECORD_FINISHED_ROUND: |
| 890 | return tool->finished_round(tool, event, session); | 902 | return tool->finished_round(tool, event, session); |
| 903 | case PERF_RECORD_ID_INDEX: | ||
| 904 | return tool->id_index(tool, event, session); | ||
| 891 | default: | 905 | default: |
| 892 | return -EINVAL; | 906 | return -EINVAL; |
| 893 | } | 907 | } |
| 894 | } | 908 | } |
| 895 | 909 | ||
| 910 | int perf_session__deliver_synth_event(struct perf_session *session, | ||
| 911 | union perf_event *event, | ||
| 912 | struct perf_sample *sample, | ||
| 913 | struct perf_tool *tool) | ||
| 914 | { | ||
| 915 | events_stats__inc(&session->stats, event->header.type); | ||
| 916 | |||
| 917 | if (event->header.type >= PERF_RECORD_USER_TYPE_START) | ||
| 918 | return perf_session__process_user_event(session, event, tool, 0); | ||
| 919 | |||
| 920 | return perf_session__deliver_event(session, event, sample, tool, 0); | ||
| 921 | } | ||
| 922 | |||
| 896 | static void event_swap(union perf_event *event, bool sample_id_all) | 923 | static void event_swap(union perf_event *event, bool sample_id_all) |
| 897 | { | 924 | { |
| 898 | perf_event__swap_op swap; | 925 | perf_event__swap_op swap; |
| @@ -1417,9 +1444,9 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample, | |||
| 1417 | if (symbol_conf.use_callchain && sample->callchain) { | 1444 | if (symbol_conf.use_callchain && sample->callchain) { |
| 1418 | struct addr_location node_al; | 1445 | struct addr_location node_al; |
| 1419 | 1446 | ||
| 1420 | if (machine__resolve_callchain(al->machine, evsel, al->thread, | 1447 | if (thread__resolve_callchain(al->thread, evsel, |
| 1421 | sample, NULL, NULL, | 1448 | sample, NULL, NULL, |
| 1422 | PERF_MAX_STACK_DEPTH) != 0) { | 1449 | PERF_MAX_STACK_DEPTH) != 0) { |
| 1423 | if (verbose) | 1450 | if (verbose) |
| 1424 | error("Failed to resolve callchain. Skipping\n"); | 1451 | error("Failed to resolve callchain. Skipping\n"); |
| 1425 | return; | 1452 | return; |
| @@ -1594,3 +1621,111 @@ int __perf_session__set_tracepoints_handlers(struct perf_session *session, | |||
| 1594 | out: | 1621 | out: |
| 1595 | return err; | 1622 | return err; |
| 1596 | } | 1623 | } |
| 1624 | |||
| 1625 | int perf_event__process_id_index(struct perf_tool *tool __maybe_unused, | ||
| 1626 | union perf_event *event, | ||
| 1627 | struct perf_session *session) | ||
| 1628 | { | ||
| 1629 | struct perf_evlist *evlist = session->evlist; | ||
| 1630 | struct id_index_event *ie = &event->id_index; | ||
| 1631 | size_t i, nr, max_nr; | ||
| 1632 | |||
| 1633 | max_nr = (ie->header.size - sizeof(struct id_index_event)) / | ||
| 1634 | sizeof(struct id_index_entry); | ||
| 1635 | nr = ie->nr; | ||
| 1636 | if (nr > max_nr) | ||
| 1637 | return -EINVAL; | ||
| 1638 | |||
| 1639 | if (dump_trace) | ||
| 1640 | fprintf(stdout, " nr: %zu\n", nr); | ||
| 1641 | |||
| 1642 | for (i = 0; i < nr; i++) { | ||
| 1643 | struct id_index_entry *e = &ie->entries[i]; | ||
| 1644 | struct perf_sample_id *sid; | ||
| 1645 | |||
| 1646 | if (dump_trace) { | ||
| 1647 | fprintf(stdout, " ... id: %"PRIu64, e->id); | ||
| 1648 | fprintf(stdout, " idx: %"PRIu64, e->idx); | ||
| 1649 | fprintf(stdout, " cpu: %"PRId64, e->cpu); | ||
| 1650 | fprintf(stdout, " tid: %"PRId64"\n", e->tid); | ||
| 1651 | } | ||
| 1652 | |||
| 1653 | sid = perf_evlist__id2sid(evlist, e->id); | ||
| 1654 | if (!sid) | ||
| 1655 | return -ENOENT; | ||
| 1656 | sid->idx = e->idx; | ||
| 1657 | sid->cpu = e->cpu; | ||
| 1658 | sid->tid = e->tid; | ||
| 1659 | } | ||
| 1660 | return 0; | ||
| 1661 | } | ||
| 1662 | |||
| 1663 | int perf_event__synthesize_id_index(struct perf_tool *tool, | ||
| 1664 | perf_event__handler_t process, | ||
| 1665 | struct perf_evlist *evlist, | ||
| 1666 | struct machine *machine) | ||
| 1667 | { | ||
| 1668 | union perf_event *ev; | ||
| 1669 | struct perf_evsel *evsel; | ||
| 1670 | size_t nr = 0, i = 0, sz, max_nr, n; | ||
| 1671 | int err; | ||
| 1672 | |||
| 1673 | pr_debug2("Synthesizing id index\n"); | ||
| 1674 | |||
| 1675 | max_nr = (UINT16_MAX - sizeof(struct id_index_event)) / | ||
| 1676 | sizeof(struct id_index_entry); | ||
| 1677 | |||
| 1678 | evlist__for_each(evlist, evsel) | ||
| 1679 | nr += evsel->ids; | ||
| 1680 | |||
| 1681 | n = nr > max_nr ? max_nr : nr; | ||
| 1682 | sz = sizeof(struct id_index_event) + n * sizeof(struct id_index_entry); | ||
| 1683 | ev = zalloc(sz); | ||
| 1684 | if (!ev) | ||
| 1685 | return -ENOMEM; | ||
| 1686 | |||
| 1687 | ev->id_index.header.type = PERF_RECORD_ID_INDEX; | ||
| 1688 | ev->id_index.header.size = sz; | ||
| 1689 | ev->id_index.nr = n; | ||
| 1690 | |||
| 1691 | evlist__for_each(evlist, evsel) { | ||
| 1692 | u32 j; | ||
| 1693 | |||
| 1694 | for (j = 0; j < evsel->ids; j++) { | ||
| 1695 | struct id_index_entry *e; | ||
| 1696 | struct perf_sample_id *sid; | ||
| 1697 | |||
| 1698 | if (i >= n) { | ||
| 1699 | err = process(tool, ev, NULL, machine); | ||
| 1700 | if (err) | ||
| 1701 | goto out_err; | ||
| 1702 | nr -= n; | ||
| 1703 | i = 0; | ||
| 1704 | } | ||
| 1705 | |||
| 1706 | e = &ev->id_index.entries[i++]; | ||
| 1707 | |||
| 1708 | e->id = evsel->id[j]; | ||
| 1709 | |||
| 1710 | sid = perf_evlist__id2sid(evlist, e->id); | ||
| 1711 | if (!sid) { | ||
| 1712 | free(ev); | ||
| 1713 | return -ENOENT; | ||
| 1714 | } | ||
| 1715 | |||
| 1716 | e->idx = sid->idx; | ||
| 1717 | e->cpu = sid->cpu; | ||
| 1718 | e->tid = sid->tid; | ||
| 1719 | } | ||
| 1720 | } | ||
| 1721 | |||
| 1722 | sz = sizeof(struct id_index_event) + nr * sizeof(struct id_index_entry); | ||
| 1723 | ev->id_index.header.size = sz; | ||
| 1724 | ev->id_index.nr = nr; | ||
| 1725 | |||
| 1726 | err = process(tool, ev, NULL, machine); | ||
| 1727 | out_err: | ||
| 1728 | free(ev); | ||
| 1729 | |||
| 1730 | return err; | ||
| 1731 | } | ||
