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 | 440 |
1 files changed, 406 insertions, 34 deletions
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 496f21cadd97..d808a328f4dc 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c | |||
@@ -24,7 +24,9 @@ | |||
24 | #include <stdio.h> | 24 | #include <stdio.h> |
25 | #include <stdlib.h> | 25 | #include <stdlib.h> |
26 | #include <string.h> | 26 | #include <string.h> |
27 | #include <stdbool.h> | ||
27 | #include <errno.h> | 28 | #include <errno.h> |
29 | #include <linux/bitmap.h> | ||
28 | 30 | ||
29 | #include "../../perf.h" | 31 | #include "../../perf.h" |
30 | #include "../debug.h" | 32 | #include "../debug.h" |
@@ -33,6 +35,10 @@ | |||
33 | #include "../util.h" | 35 | #include "../util.h" |
34 | #include "../event.h" | 36 | #include "../event.h" |
35 | #include "../thread.h" | 37 | #include "../thread.h" |
38 | #include "../comm.h" | ||
39 | #include "../machine.h" | ||
40 | #include "../db-export.h" | ||
41 | #include "../thread-stack.h" | ||
36 | #include "../trace-event.h" | 42 | #include "../trace-event.h" |
37 | #include "../machine.h" | 43 | #include "../machine.h" |
38 | 44 | ||
@@ -41,7 +47,7 @@ PyMODINIT_FUNC initperf_trace_context(void); | |||
41 | #define FTRACE_MAX_EVENT \ | 47 | #define FTRACE_MAX_EVENT \ |
42 | ((1 << (sizeof(unsigned short) * 8)) - 1) | 48 | ((1 << (sizeof(unsigned short) * 8)) - 1) |
43 | 49 | ||
44 | struct event_format *events[FTRACE_MAX_EVENT]; | 50 | static DECLARE_BITMAP(events_defined, FTRACE_MAX_EVENT); |
45 | 51 | ||
46 | #define MAX_FIELDS 64 | 52 | #define MAX_FIELDS 64 |
47 | #define N_COMMON_FIELDS 7 | 53 | #define N_COMMON_FIELDS 7 |
@@ -53,6 +59,24 @@ static int zero_flag_atom; | |||
53 | 59 | ||
54 | static PyObject *main_module, *main_dict; | 60 | static PyObject *main_module, *main_dict; |
55 | 61 | ||
62 | struct tables { | ||
63 | struct db_export dbe; | ||
64 | PyObject *evsel_handler; | ||
65 | PyObject *machine_handler; | ||
66 | PyObject *thread_handler; | ||
67 | PyObject *comm_handler; | ||
68 | PyObject *comm_thread_handler; | ||
69 | PyObject *dso_handler; | ||
70 | PyObject *symbol_handler; | ||
71 | PyObject *branch_type_handler; | ||
72 | PyObject *sample_handler; | ||
73 | PyObject *call_path_handler; | ||
74 | PyObject *call_return_handler; | ||
75 | bool db_export_mode; | ||
76 | }; | ||
77 | |||
78 | static struct tables tables_global; | ||
79 | |||
56 | static void handler_call_die(const char *handler_name) NORETURN; | 80 | static void handler_call_die(const char *handler_name) NORETURN; |
57 | static void handler_call_die(const char *handler_name) | 81 | static void handler_call_die(const char *handler_name) |
58 | { | 82 | { |
@@ -232,31 +256,6 @@ static void define_event_symbols(struct event_format *event, | |||
232 | define_event_symbols(event, ev_name, args->next); | 256 | define_event_symbols(event, ev_name, args->next); |
233 | } | 257 | } |
234 | 258 | ||
235 | static inline struct event_format *find_cache_event(struct perf_evsel *evsel) | ||
236 | { | ||
237 | static char ev_name[256]; | ||
238 | struct event_format *event; | ||
239 | int type = evsel->attr.config; | ||
240 | |||
241 | /* | ||
242 | * XXX: Do we really need to cache this since now we have evsel->tp_format | ||
243 | * cached already? Need to re-read this "cache" routine that as well calls | ||
244 | * define_event_symbols() :-\ | ||
245 | */ | ||
246 | if (events[type]) | ||
247 | return events[type]; | ||
248 | |||
249 | events[type] = event = evsel->tp_format; | ||
250 | if (!event) | ||
251 | return NULL; | ||
252 | |||
253 | sprintf(ev_name, "%s__%s", event->system, event->name); | ||
254 | |||
255 | define_event_symbols(event, ev_name, event->print_fmt.args); | ||
256 | |||
257 | return event; | ||
258 | } | ||
259 | |||
260 | static PyObject *get_field_numeric_entry(struct event_format *event, | 259 | static PyObject *get_field_numeric_entry(struct event_format *event, |
261 | struct format_field *field, void *data) | 260 | struct format_field *field, void *data) |
262 | { | 261 | { |
@@ -312,9 +311,9 @@ static PyObject *python_process_callchain(struct perf_sample *sample, | |||
312 | if (!symbol_conf.use_callchain || !sample->callchain) | 311 | if (!symbol_conf.use_callchain || !sample->callchain) |
313 | goto exit; | 312 | goto exit; |
314 | 313 | ||
315 | if (machine__resolve_callchain(al->machine, evsel, al->thread, | 314 | if (thread__resolve_callchain(al->thread, evsel, |
316 | sample, NULL, NULL, | 315 | sample, NULL, NULL, |
317 | PERF_MAX_STACK_DEPTH) != 0) { | 316 | PERF_MAX_STACK_DEPTH) != 0) { |
318 | pr_err("Failed to resolve callchain. Skipping\n"); | 317 | pr_err("Failed to resolve callchain. Skipping\n"); |
319 | goto exit; | 318 | goto exit; |
320 | } | 319 | } |
@@ -380,12 +379,12 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
380 | struct thread *thread, | 379 | struct thread *thread, |
381 | struct addr_location *al) | 380 | struct addr_location *al) |
382 | { | 381 | { |
382 | struct event_format *event = evsel->tp_format; | ||
383 | PyObject *handler, *context, *t, *obj, *callchain; | 383 | PyObject *handler, *context, *t, *obj, *callchain; |
384 | PyObject *dict = NULL; | 384 | PyObject *dict = NULL; |
385 | static char handler_name[256]; | 385 | static char handler_name[256]; |
386 | struct format_field *field; | 386 | struct format_field *field; |
387 | unsigned long s, ns; | 387 | unsigned long s, ns; |
388 | struct event_format *event; | ||
389 | unsigned n = 0; | 388 | unsigned n = 0; |
390 | int pid; | 389 | int pid; |
391 | int cpu = sample->cpu; | 390 | int cpu = sample->cpu; |
@@ -397,7 +396,6 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
397 | if (!t) | 396 | if (!t) |
398 | Py_FatalError("couldn't create Python tuple"); | 397 | Py_FatalError("couldn't create Python tuple"); |
399 | 398 | ||
400 | event = find_cache_event(evsel); | ||
401 | if (!event) | 399 | if (!event) |
402 | die("ug! no event found for type %d", (int)evsel->attr.config); | 400 | die("ug! no event found for type %d", (int)evsel->attr.config); |
403 | 401 | ||
@@ -405,6 +403,9 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
405 | 403 | ||
406 | sprintf(handler_name, "%s__%s", event->system, event->name); | 404 | sprintf(handler_name, "%s__%s", event->system, event->name); |
407 | 405 | ||
406 | if (!test_and_set_bit(event->id, events_defined)) | ||
407 | define_event_symbols(event, handler_name, event->print_fmt.args); | ||
408 | |||
408 | handler = get_handler(handler_name); | 409 | handler = get_handler(handler_name); |
409 | if (!handler) { | 410 | if (!handler) { |
410 | dict = PyDict_New(); | 411 | dict = PyDict_New(); |
@@ -475,6 +476,289 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
475 | Py_DECREF(t); | 476 | Py_DECREF(t); |
476 | } | 477 | } |
477 | 478 | ||
479 | static PyObject *tuple_new(unsigned int sz) | ||
480 | { | ||
481 | PyObject *t; | ||
482 | |||
483 | t = PyTuple_New(sz); | ||
484 | if (!t) | ||
485 | Py_FatalError("couldn't create Python tuple"); | ||
486 | return t; | ||
487 | } | ||
488 | |||
489 | static int tuple_set_u64(PyObject *t, unsigned int pos, u64 val) | ||
490 | { | ||
491 | #if BITS_PER_LONG == 64 | ||
492 | return PyTuple_SetItem(t, pos, PyInt_FromLong(val)); | ||
493 | #endif | ||
494 | #if BITS_PER_LONG == 32 | ||
495 | return PyTuple_SetItem(t, pos, PyLong_FromLongLong(val)); | ||
496 | #endif | ||
497 | } | ||
498 | |||
499 | static int tuple_set_s32(PyObject *t, unsigned int pos, s32 val) | ||
500 | { | ||
501 | return PyTuple_SetItem(t, pos, PyInt_FromLong(val)); | ||
502 | } | ||
503 | |||
504 | static int tuple_set_string(PyObject *t, unsigned int pos, const char *s) | ||
505 | { | ||
506 | return PyTuple_SetItem(t, pos, PyString_FromString(s)); | ||
507 | } | ||
508 | |||
509 | static int python_export_evsel(struct db_export *dbe, struct perf_evsel *evsel) | ||
510 | { | ||
511 | struct tables *tables = container_of(dbe, struct tables, dbe); | ||
512 | PyObject *t; | ||
513 | |||
514 | t = tuple_new(2); | ||
515 | |||
516 | tuple_set_u64(t, 0, evsel->db_id); | ||
517 | tuple_set_string(t, 1, perf_evsel__name(evsel)); | ||
518 | |||
519 | call_object(tables->evsel_handler, t, "evsel_table"); | ||
520 | |||
521 | Py_DECREF(t); | ||
522 | |||
523 | return 0; | ||
524 | } | ||
525 | |||
526 | static int python_export_machine(struct db_export *dbe, | ||
527 | struct machine *machine) | ||
528 | { | ||
529 | struct tables *tables = container_of(dbe, struct tables, dbe); | ||
530 | PyObject *t; | ||
531 | |||
532 | t = tuple_new(3); | ||
533 | |||
534 | tuple_set_u64(t, 0, machine->db_id); | ||
535 | tuple_set_s32(t, 1, machine->pid); | ||
536 | tuple_set_string(t, 2, machine->root_dir ? machine->root_dir : ""); | ||
537 | |||
538 | call_object(tables->machine_handler, t, "machine_table"); | ||
539 | |||
540 | Py_DECREF(t); | ||
541 | |||
542 | return 0; | ||
543 | } | ||
544 | |||
545 | static int python_export_thread(struct db_export *dbe, struct thread *thread, | ||
546 | u64 main_thread_db_id, struct machine *machine) | ||
547 | { | ||
548 | struct tables *tables = container_of(dbe, struct tables, dbe); | ||
549 | PyObject *t; | ||
550 | |||
551 | t = tuple_new(5); | ||
552 | |||
553 | tuple_set_u64(t, 0, thread->db_id); | ||
554 | tuple_set_u64(t, 1, machine->db_id); | ||
555 | tuple_set_u64(t, 2, main_thread_db_id); | ||
556 | tuple_set_s32(t, 3, thread->pid_); | ||
557 | tuple_set_s32(t, 4, thread->tid); | ||
558 | |||
559 | call_object(tables->thread_handler, t, "thread_table"); | ||
560 | |||
561 | Py_DECREF(t); | ||
562 | |||
563 | return 0; | ||
564 | } | ||
565 | |||
566 | static int python_export_comm(struct db_export *dbe, struct comm *comm) | ||
567 | { | ||
568 | struct tables *tables = container_of(dbe, struct tables, dbe); | ||
569 | PyObject *t; | ||
570 | |||
571 | t = tuple_new(2); | ||
572 | |||
573 | tuple_set_u64(t, 0, comm->db_id); | ||
574 | tuple_set_string(t, 1, comm__str(comm)); | ||
575 | |||
576 | call_object(tables->comm_handler, t, "comm_table"); | ||
577 | |||
578 | Py_DECREF(t); | ||
579 | |||
580 | return 0; | ||
581 | } | ||
582 | |||
583 | static int python_export_comm_thread(struct db_export *dbe, u64 db_id, | ||
584 | struct comm *comm, struct thread *thread) | ||
585 | { | ||
586 | struct tables *tables = container_of(dbe, struct tables, dbe); | ||
587 | PyObject *t; | ||
588 | |||
589 | t = tuple_new(3); | ||
590 | |||
591 | tuple_set_u64(t, 0, db_id); | ||
592 | tuple_set_u64(t, 1, comm->db_id); | ||
593 | tuple_set_u64(t, 2, thread->db_id); | ||
594 | |||
595 | call_object(tables->comm_thread_handler, t, "comm_thread_table"); | ||
596 | |||
597 | Py_DECREF(t); | ||
598 | |||
599 | return 0; | ||
600 | } | ||
601 | |||
602 | static int python_export_dso(struct db_export *dbe, struct dso *dso, | ||
603 | struct machine *machine) | ||
604 | { | ||
605 | struct tables *tables = container_of(dbe, struct tables, dbe); | ||
606 | char sbuild_id[BUILD_ID_SIZE * 2 + 1]; | ||
607 | PyObject *t; | ||
608 | |||
609 | build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id); | ||
610 | |||
611 | t = tuple_new(5); | ||
612 | |||
613 | tuple_set_u64(t, 0, dso->db_id); | ||
614 | tuple_set_u64(t, 1, machine->db_id); | ||
615 | tuple_set_string(t, 2, dso->short_name); | ||
616 | tuple_set_string(t, 3, dso->long_name); | ||
617 | tuple_set_string(t, 4, sbuild_id); | ||
618 | |||
619 | call_object(tables->dso_handler, t, "dso_table"); | ||
620 | |||
621 | Py_DECREF(t); | ||
622 | |||
623 | return 0; | ||
624 | } | ||
625 | |||
626 | static int python_export_symbol(struct db_export *dbe, struct symbol *sym, | ||
627 | struct dso *dso) | ||
628 | { | ||
629 | struct tables *tables = container_of(dbe, struct tables, dbe); | ||
630 | u64 *sym_db_id = symbol__priv(sym); | ||
631 | PyObject *t; | ||
632 | |||
633 | t = tuple_new(6); | ||
634 | |||
635 | tuple_set_u64(t, 0, *sym_db_id); | ||
636 | tuple_set_u64(t, 1, dso->db_id); | ||
637 | tuple_set_u64(t, 2, sym->start); | ||
638 | tuple_set_u64(t, 3, sym->end); | ||
639 | tuple_set_s32(t, 4, sym->binding); | ||
640 | tuple_set_string(t, 5, sym->name); | ||
641 | |||
642 | call_object(tables->symbol_handler, t, "symbol_table"); | ||
643 | |||
644 | Py_DECREF(t); | ||
645 | |||
646 | return 0; | ||
647 | } | ||
648 | |||
649 | static int python_export_branch_type(struct db_export *dbe, u32 branch_type, | ||
650 | const char *name) | ||
651 | { | ||
652 | struct tables *tables = container_of(dbe, struct tables, dbe); | ||
653 | PyObject *t; | ||
654 | |||
655 | t = tuple_new(2); | ||
656 | |||
657 | tuple_set_s32(t, 0, branch_type); | ||
658 | tuple_set_string(t, 1, name); | ||
659 | |||
660 | call_object(tables->branch_type_handler, t, "branch_type_table"); | ||
661 | |||
662 | Py_DECREF(t); | ||
663 | |||
664 | return 0; | ||
665 | } | ||
666 | |||
667 | static int python_export_sample(struct db_export *dbe, | ||
668 | struct export_sample *es) | ||
669 | { | ||
670 | struct tables *tables = container_of(dbe, struct tables, dbe); | ||
671 | PyObject *t; | ||
672 | |||
673 | t = tuple_new(21); | ||
674 | |||
675 | tuple_set_u64(t, 0, es->db_id); | ||
676 | tuple_set_u64(t, 1, es->evsel->db_id); | ||
677 | tuple_set_u64(t, 2, es->al->machine->db_id); | ||
678 | tuple_set_u64(t, 3, es->thread->db_id); | ||
679 | tuple_set_u64(t, 4, es->comm_db_id); | ||
680 | tuple_set_u64(t, 5, es->dso_db_id); | ||
681 | tuple_set_u64(t, 6, es->sym_db_id); | ||
682 | tuple_set_u64(t, 7, es->offset); | ||
683 | tuple_set_u64(t, 8, es->sample->ip); | ||
684 | tuple_set_u64(t, 9, es->sample->time); | ||
685 | tuple_set_s32(t, 10, es->sample->cpu); | ||
686 | tuple_set_u64(t, 11, es->addr_dso_db_id); | ||
687 | tuple_set_u64(t, 12, es->addr_sym_db_id); | ||
688 | tuple_set_u64(t, 13, es->addr_offset); | ||
689 | tuple_set_u64(t, 14, es->sample->addr); | ||
690 | tuple_set_u64(t, 15, es->sample->period); | ||
691 | tuple_set_u64(t, 16, es->sample->weight); | ||
692 | tuple_set_u64(t, 17, es->sample->transaction); | ||
693 | tuple_set_u64(t, 18, es->sample->data_src); | ||
694 | tuple_set_s32(t, 19, es->sample->flags & PERF_BRANCH_MASK); | ||
695 | tuple_set_s32(t, 20, !!(es->sample->flags & PERF_IP_FLAG_IN_TX)); | ||
696 | |||
697 | call_object(tables->sample_handler, t, "sample_table"); | ||
698 | |||
699 | Py_DECREF(t); | ||
700 | |||
701 | return 0; | ||
702 | } | ||
703 | |||
704 | static int python_export_call_path(struct db_export *dbe, struct call_path *cp) | ||
705 | { | ||
706 | struct tables *tables = container_of(dbe, struct tables, dbe); | ||
707 | PyObject *t; | ||
708 | u64 parent_db_id, sym_db_id; | ||
709 | |||
710 | parent_db_id = cp->parent ? cp->parent->db_id : 0; | ||
711 | sym_db_id = cp->sym ? *(u64 *)symbol__priv(cp->sym) : 0; | ||
712 | |||
713 | t = tuple_new(4); | ||
714 | |||
715 | tuple_set_u64(t, 0, cp->db_id); | ||
716 | tuple_set_u64(t, 1, parent_db_id); | ||
717 | tuple_set_u64(t, 2, sym_db_id); | ||
718 | tuple_set_u64(t, 3, cp->ip); | ||
719 | |||
720 | call_object(tables->call_path_handler, t, "call_path_table"); | ||
721 | |||
722 | Py_DECREF(t); | ||
723 | |||
724 | return 0; | ||
725 | } | ||
726 | |||
727 | static int python_export_call_return(struct db_export *dbe, | ||
728 | struct call_return *cr) | ||
729 | { | ||
730 | struct tables *tables = container_of(dbe, struct tables, dbe); | ||
731 | u64 comm_db_id = cr->comm ? cr->comm->db_id : 0; | ||
732 | PyObject *t; | ||
733 | |||
734 | t = tuple_new(11); | ||
735 | |||
736 | tuple_set_u64(t, 0, cr->db_id); | ||
737 | tuple_set_u64(t, 1, cr->thread->db_id); | ||
738 | tuple_set_u64(t, 2, comm_db_id); | ||
739 | tuple_set_u64(t, 3, cr->cp->db_id); | ||
740 | tuple_set_u64(t, 4, cr->call_time); | ||
741 | tuple_set_u64(t, 5, cr->return_time); | ||
742 | tuple_set_u64(t, 6, cr->branch_count); | ||
743 | tuple_set_u64(t, 7, cr->call_ref); | ||
744 | tuple_set_u64(t, 8, cr->return_ref); | ||
745 | tuple_set_u64(t, 9, cr->cp->parent->db_id); | ||
746 | tuple_set_s32(t, 10, cr->flags); | ||
747 | |||
748 | call_object(tables->call_return_handler, t, "call_return_table"); | ||
749 | |||
750 | Py_DECREF(t); | ||
751 | |||
752 | return 0; | ||
753 | } | ||
754 | |||
755 | static int python_process_call_return(struct call_return *cr, void *data) | ||
756 | { | ||
757 | struct db_export *dbe = data; | ||
758 | |||
759 | return db_export__call_return(dbe, cr); | ||
760 | } | ||
761 | |||
478 | static void python_process_general_event(struct perf_sample *sample, | 762 | static void python_process_general_event(struct perf_sample *sample, |
479 | struct perf_evsel *evsel, | 763 | struct perf_evsel *evsel, |
480 | struct thread *thread, | 764 | struct thread *thread, |
@@ -551,19 +835,25 @@ exit: | |||
551 | Py_DECREF(t); | 835 | Py_DECREF(t); |
552 | } | 836 | } |
553 | 837 | ||
554 | static void python_process_event(union perf_event *event __maybe_unused, | 838 | static void python_process_event(union perf_event *event, |
555 | struct perf_sample *sample, | 839 | struct perf_sample *sample, |
556 | struct perf_evsel *evsel, | 840 | struct perf_evsel *evsel, |
557 | struct thread *thread, | 841 | struct thread *thread, |
558 | struct addr_location *al) | 842 | struct addr_location *al) |
559 | { | 843 | { |
844 | struct tables *tables = &tables_global; | ||
845 | |||
560 | switch (evsel->attr.type) { | 846 | switch (evsel->attr.type) { |
561 | case PERF_TYPE_TRACEPOINT: | 847 | case PERF_TYPE_TRACEPOINT: |
562 | python_process_tracepoint(sample, evsel, thread, al); | 848 | python_process_tracepoint(sample, evsel, thread, al); |
563 | break; | 849 | break; |
564 | /* Reserve for future process_hw/sw/raw APIs */ | 850 | /* Reserve for future process_hw/sw/raw APIs */ |
565 | default: | 851 | default: |
566 | python_process_general_event(sample, evsel, thread, al); | 852 | if (tables->db_export_mode) |
853 | db_export__sample(&tables->dbe, event, sample, evsel, | ||
854 | thread, al); | ||
855 | else | ||
856 | python_process_general_event(sample, evsel, thread, al); | ||
567 | } | 857 | } |
568 | } | 858 | } |
569 | 859 | ||
@@ -589,11 +879,79 @@ error: | |||
589 | return -1; | 879 | return -1; |
590 | } | 880 | } |
591 | 881 | ||
882 | #define SET_TABLE_HANDLER_(name, handler_name, table_name) do { \ | ||
883 | tables->handler_name = get_handler(#table_name); \ | ||
884 | if (tables->handler_name) \ | ||
885 | tables->dbe.export_ ## name = python_export_ ## name; \ | ||
886 | } while (0) | ||
887 | |||
888 | #define SET_TABLE_HANDLER(name) \ | ||
889 | SET_TABLE_HANDLER_(name, name ## _handler, name ## _table) | ||
890 | |||
891 | static void set_table_handlers(struct tables *tables) | ||
892 | { | ||
893 | const char *perf_db_export_mode = "perf_db_export_mode"; | ||
894 | const char *perf_db_export_calls = "perf_db_export_calls"; | ||
895 | PyObject *db_export_mode, *db_export_calls; | ||
896 | bool export_calls = false; | ||
897 | int ret; | ||
898 | |||
899 | memset(tables, 0, sizeof(struct tables)); | ||
900 | if (db_export__init(&tables->dbe)) | ||
901 | Py_FatalError("failed to initialize export"); | ||
902 | |||
903 | db_export_mode = PyDict_GetItemString(main_dict, perf_db_export_mode); | ||
904 | if (!db_export_mode) | ||
905 | return; | ||
906 | |||
907 | ret = PyObject_IsTrue(db_export_mode); | ||
908 | if (ret == -1) | ||
909 | handler_call_die(perf_db_export_mode); | ||
910 | if (!ret) | ||
911 | return; | ||
912 | |||
913 | tables->dbe.crp = NULL; | ||
914 | db_export_calls = PyDict_GetItemString(main_dict, perf_db_export_calls); | ||
915 | if (db_export_calls) { | ||
916 | ret = PyObject_IsTrue(db_export_calls); | ||
917 | if (ret == -1) | ||
918 | handler_call_die(perf_db_export_calls); | ||
919 | export_calls = !!ret; | ||
920 | } | ||
921 | |||
922 | if (export_calls) { | ||
923 | tables->dbe.crp = | ||
924 | call_return_processor__new(python_process_call_return, | ||
925 | &tables->dbe); | ||
926 | if (!tables->dbe.crp) | ||
927 | Py_FatalError("failed to create calls processor"); | ||
928 | } | ||
929 | |||
930 | tables->db_export_mode = true; | ||
931 | /* | ||
932 | * Reserve per symbol space for symbol->db_id via symbol__priv() | ||
933 | */ | ||
934 | symbol_conf.priv_size = sizeof(u64); | ||
935 | |||
936 | SET_TABLE_HANDLER(evsel); | ||
937 | SET_TABLE_HANDLER(machine); | ||
938 | SET_TABLE_HANDLER(thread); | ||
939 | SET_TABLE_HANDLER(comm); | ||
940 | SET_TABLE_HANDLER(comm_thread); | ||
941 | SET_TABLE_HANDLER(dso); | ||
942 | SET_TABLE_HANDLER(symbol); | ||
943 | SET_TABLE_HANDLER(branch_type); | ||
944 | SET_TABLE_HANDLER(sample); | ||
945 | SET_TABLE_HANDLER(call_path); | ||
946 | SET_TABLE_HANDLER(call_return); | ||
947 | } | ||
948 | |||
592 | /* | 949 | /* |
593 | * Start trace script | 950 | * Start trace script |
594 | */ | 951 | */ |
595 | static int python_start_script(const char *script, int argc, const char **argv) | 952 | static int python_start_script(const char *script, int argc, const char **argv) |
596 | { | 953 | { |
954 | struct tables *tables = &tables_global; | ||
597 | const char **command_line; | 955 | const char **command_line; |
598 | char buf[PATH_MAX]; | 956 | char buf[PATH_MAX]; |
599 | int i, err = 0; | 957 | int i, err = 0; |
@@ -632,6 +990,14 @@ static int python_start_script(const char *script, int argc, const char **argv) | |||
632 | 990 | ||
633 | free(command_line); | 991 | free(command_line); |
634 | 992 | ||
993 | set_table_handlers(tables); | ||
994 | |||
995 | if (tables->db_export_mode) { | ||
996 | err = db_export__branch_types(&tables->dbe); | ||
997 | if (err) | ||
998 | goto error; | ||
999 | } | ||
1000 | |||
635 | return err; | 1001 | return err; |
636 | error: | 1002 | error: |
637 | Py_Finalize(); | 1003 | Py_Finalize(); |
@@ -642,7 +1008,9 @@ error: | |||
642 | 1008 | ||
643 | static int python_flush_script(void) | 1009 | static int python_flush_script(void) |
644 | { | 1010 | { |
645 | return 0; | 1011 | struct tables *tables = &tables_global; |
1012 | |||
1013 | return db_export__flush(&tables->dbe); | ||
646 | } | 1014 | } |
647 | 1015 | ||
648 | /* | 1016 | /* |
@@ -650,8 +1018,12 @@ static int python_flush_script(void) | |||
650 | */ | 1018 | */ |
651 | static int python_stop_script(void) | 1019 | static int python_stop_script(void) |
652 | { | 1020 | { |
1021 | struct tables *tables = &tables_global; | ||
1022 | |||
653 | try_call_object("trace_end", NULL); | 1023 | try_call_object("trace_end", NULL); |
654 | 1024 | ||
1025 | db_export__exit(&tables->dbe); | ||
1026 | |||
655 | Py_XDECREF(main_dict); | 1027 | Py_XDECREF(main_dict); |
656 | Py_XDECREF(main_module); | 1028 | Py_XDECREF(main_module); |
657 | Py_Finalize(); | 1029 | Py_Finalize(); |