diff options
Diffstat (limited to 'tools/perf/util/scripting-engines/trace-event-python.c')
-rw-r--r-- | tools/perf/util/scripting-engines/trace-event-python.c | 47 |
1 files changed, 41 insertions, 6 deletions
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index fbd05242b4e5..ff134700bf30 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include "../thread-stack.h" | 41 | #include "../thread-stack.h" |
42 | #include "../trace-event.h" | 42 | #include "../trace-event.h" |
43 | #include "../machine.h" | 43 | #include "../machine.h" |
44 | #include "../call-path.h" | ||
44 | #include "thread_map.h" | 45 | #include "thread_map.h" |
45 | #include "cpumap.h" | 46 | #include "cpumap.h" |
46 | #include "stat.h" | 47 | #include "stat.h" |
@@ -323,7 +324,7 @@ static PyObject *python_process_callchain(struct perf_sample *sample, | |||
323 | if (!symbol_conf.use_callchain || !sample->callchain) | 324 | if (!symbol_conf.use_callchain || !sample->callchain) |
324 | goto exit; | 325 | goto exit; |
325 | 326 | ||
326 | if (thread__resolve_callchain(al->thread, evsel, | 327 | if (thread__resolve_callchain(al->thread, &callchain_cursor, evsel, |
327 | sample, NULL, NULL, | 328 | sample, NULL, NULL, |
328 | scripting_max_stack) != 0) { | 329 | scripting_max_stack) != 0) { |
329 | pr_err("Failed to resolve callchain. Skipping\n"); | 330 | pr_err("Failed to resolve callchain. Skipping\n"); |
@@ -407,8 +408,11 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
407 | if (!t) | 408 | if (!t) |
408 | Py_FatalError("couldn't create Python tuple"); | 409 | Py_FatalError("couldn't create Python tuple"); |
409 | 410 | ||
410 | if (!event) | 411 | if (!event) { |
411 | die("ug! no event found for type %d", (int)evsel->attr.config); | 412 | snprintf(handler_name, sizeof(handler_name), |
413 | "ug! no event found for type %" PRIu64, (u64)evsel->attr.config); | ||
414 | Py_FatalError(handler_name); | ||
415 | } | ||
412 | 416 | ||
413 | pid = raw_field_value(event, "common_pid", data); | 417 | pid = raw_field_value(event, "common_pid", data); |
414 | 418 | ||
@@ -614,7 +618,7 @@ static int python_export_dso(struct db_export *dbe, struct dso *dso, | |||
614 | struct machine *machine) | 618 | struct machine *machine) |
615 | { | 619 | { |
616 | struct tables *tables = container_of(dbe, struct tables, dbe); | 620 | struct tables *tables = container_of(dbe, struct tables, dbe); |
617 | char sbuild_id[BUILD_ID_SIZE * 2 + 1]; | 621 | char sbuild_id[SBUILD_ID_SIZE]; |
618 | PyObject *t; | 622 | PyObject *t; |
619 | 623 | ||
620 | build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id); | 624 | build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id); |
@@ -681,7 +685,7 @@ static int python_export_sample(struct db_export *dbe, | |||
681 | struct tables *tables = container_of(dbe, struct tables, dbe); | 685 | struct tables *tables = container_of(dbe, struct tables, dbe); |
682 | PyObject *t; | 686 | PyObject *t; |
683 | 687 | ||
684 | t = tuple_new(21); | 688 | t = tuple_new(22); |
685 | 689 | ||
686 | tuple_set_u64(t, 0, es->db_id); | 690 | tuple_set_u64(t, 0, es->db_id); |
687 | tuple_set_u64(t, 1, es->evsel->db_id); | 691 | tuple_set_u64(t, 1, es->evsel->db_id); |
@@ -704,6 +708,7 @@ static int python_export_sample(struct db_export *dbe, | |||
704 | tuple_set_u64(t, 18, es->sample->data_src); | 708 | tuple_set_u64(t, 18, es->sample->data_src); |
705 | tuple_set_s32(t, 19, es->sample->flags & PERF_BRANCH_MASK); | 709 | tuple_set_s32(t, 19, es->sample->flags & PERF_BRANCH_MASK); |
706 | tuple_set_s32(t, 20, !!(es->sample->flags & PERF_IP_FLAG_IN_TX)); | 710 | tuple_set_s32(t, 20, !!(es->sample->flags & PERF_IP_FLAG_IN_TX)); |
711 | tuple_set_u64(t, 21, es->call_path_id); | ||
707 | 712 | ||
708 | call_object(tables->sample_handler, t, "sample_table"); | 713 | call_object(tables->sample_handler, t, "sample_table"); |
709 | 714 | ||
@@ -998,8 +1003,10 @@ static void set_table_handlers(struct tables *tables) | |||
998 | { | 1003 | { |
999 | const char *perf_db_export_mode = "perf_db_export_mode"; | 1004 | const char *perf_db_export_mode = "perf_db_export_mode"; |
1000 | const char *perf_db_export_calls = "perf_db_export_calls"; | 1005 | const char *perf_db_export_calls = "perf_db_export_calls"; |
1001 | PyObject *db_export_mode, *db_export_calls; | 1006 | const char *perf_db_export_callchains = "perf_db_export_callchains"; |
1007 | PyObject *db_export_mode, *db_export_calls, *db_export_callchains; | ||
1002 | bool export_calls = false; | 1008 | bool export_calls = false; |
1009 | bool export_callchains = false; | ||
1003 | int ret; | 1010 | int ret; |
1004 | 1011 | ||
1005 | memset(tables, 0, sizeof(struct tables)); | 1012 | memset(tables, 0, sizeof(struct tables)); |
@@ -1016,6 +1023,7 @@ static void set_table_handlers(struct tables *tables) | |||
1016 | if (!ret) | 1023 | if (!ret) |
1017 | return; | 1024 | return; |
1018 | 1025 | ||
1026 | /* handle export calls */ | ||
1019 | tables->dbe.crp = NULL; | 1027 | tables->dbe.crp = NULL; |
1020 | db_export_calls = PyDict_GetItemString(main_dict, perf_db_export_calls); | 1028 | db_export_calls = PyDict_GetItemString(main_dict, perf_db_export_calls); |
1021 | if (db_export_calls) { | 1029 | if (db_export_calls) { |
@@ -1033,6 +1041,33 @@ static void set_table_handlers(struct tables *tables) | |||
1033 | Py_FatalError("failed to create calls processor"); | 1041 | Py_FatalError("failed to create calls processor"); |
1034 | } | 1042 | } |
1035 | 1043 | ||
1044 | /* handle export callchains */ | ||
1045 | tables->dbe.cpr = NULL; | ||
1046 | db_export_callchains = PyDict_GetItemString(main_dict, | ||
1047 | perf_db_export_callchains); | ||
1048 | if (db_export_callchains) { | ||
1049 | ret = PyObject_IsTrue(db_export_callchains); | ||
1050 | if (ret == -1) | ||
1051 | handler_call_die(perf_db_export_callchains); | ||
1052 | export_callchains = !!ret; | ||
1053 | } | ||
1054 | |||
1055 | if (export_callchains) { | ||
1056 | /* | ||
1057 | * Attempt to use the call path root from the call return | ||
1058 | * processor, if the call return processor is in use. Otherwise, | ||
1059 | * we allocate a new call path root. This prevents exporting | ||
1060 | * duplicate call path ids when both are in use simultaniously. | ||
1061 | */ | ||
1062 | if (tables->dbe.crp) | ||
1063 | tables->dbe.cpr = tables->dbe.crp->cpr; | ||
1064 | else | ||
1065 | tables->dbe.cpr = call_path_root__new(); | ||
1066 | |||
1067 | if (!tables->dbe.cpr) | ||
1068 | Py_FatalError("failed to create call path root"); | ||
1069 | } | ||
1070 | |||
1036 | tables->db_export_mode = true; | 1071 | tables->db_export_mode = true; |
1037 | /* | 1072 | /* |
1038 | * Reserve per symbol space for symbol->db_id via symbol__priv() | 1073 | * Reserve per symbol space for symbol->db_id via symbol__priv() |