123d15e86SLluís /* 223d15e86SLluís * Interface for configuring and controlling the state of tracing events. 323d15e86SLluís * 45b808275SLluís Vilanova * Copyright (C) 2011-2014 Lluís Vilanova <vilanova@ac.upc.edu> 523d15e86SLluís * 6b1bae816SLluís Vilanova * This work is licensed under the terms of the GNU GPL, version 2 or later. 7b1bae816SLluís Vilanova * See the COPYING file in the top-level directory. 823d15e86SLluís */ 923d15e86SLluís 1023d15e86SLluís #include "trace/control.h" 115b808275SLluís Vilanova #ifdef CONFIG_TRACE_SIMPLE 125b808275SLluís Vilanova #include "trace/simple.h" 135b808275SLluís Vilanova #endif 145b808275SLluís Vilanova #ifdef CONFIG_TRACE_FTRACE 155b808275SLluís Vilanova #include "trace/ftrace.h" 165b808275SLluís Vilanova #endif 17*a35d9be6SAlexey Kardashevskiy #include "qemu/error-report.h" 1823d15e86SLluís 19b1bae816SLluís Vilanova TraceEvent *trace_event_name(const char *name) 20b1bae816SLluís Vilanova { 21b1bae816SLluís Vilanova assert(name != NULL); 22b1bae816SLluís Vilanova 23b1bae816SLluís Vilanova TraceEventID i; 24b1bae816SLluís Vilanova for (i = 0; i < trace_event_count(); i++) { 25b1bae816SLluís Vilanova TraceEvent *ev = trace_event_id(i); 26b1bae816SLluís Vilanova if (strcmp(trace_event_get_name(ev), name) == 0) { 27b1bae816SLluís Vilanova return ev; 28b1bae816SLluís Vilanova } 29b1bae816SLluís Vilanova } 30b1bae816SLluís Vilanova return NULL; 31b1bae816SLluís Vilanova } 32b1bae816SLluís Vilanova 33b1bae816SLluís Vilanova static bool pattern_glob(const char *pat, const char *ev) 34b1bae816SLluís Vilanova { 35b1bae816SLluís Vilanova while (*pat != '\0' && *ev != '\0') { 36b1bae816SLluís Vilanova if (*pat == *ev) { 37b1bae816SLluís Vilanova pat++; 38b1bae816SLluís Vilanova ev++; 39b1bae816SLluís Vilanova } 40b1bae816SLluís Vilanova else if (*pat == '*') { 41b1bae816SLluís Vilanova if (pattern_glob(pat, ev+1)) { 42b1bae816SLluís Vilanova return true; 43b1bae816SLluís Vilanova } else if (pattern_glob(pat+1, ev)) { 44b1bae816SLluís Vilanova return true; 45b1bae816SLluís Vilanova } else { 46b1bae816SLluís Vilanova return false; 47b1bae816SLluís Vilanova } 48b1bae816SLluís Vilanova } else { 49b1bae816SLluís Vilanova return false; 50b1bae816SLluís Vilanova } 51b1bae816SLluís Vilanova } 52b1bae816SLluís Vilanova 53b1bae816SLluís Vilanova while (*pat == '*') { 54b1bae816SLluís Vilanova pat++; 55b1bae816SLluís Vilanova } 56b1bae816SLluís Vilanova 57b1bae816SLluís Vilanova if (*pat == '\0' && *ev == '\0') { 58b1bae816SLluís Vilanova return true; 59b1bae816SLluís Vilanova } else { 60b1bae816SLluís Vilanova return false; 61b1bae816SLluís Vilanova } 62b1bae816SLluís Vilanova } 63b1bae816SLluís Vilanova 64b1bae816SLluís Vilanova TraceEvent *trace_event_pattern(const char *pat, TraceEvent *ev) 65b1bae816SLluís Vilanova { 66b1bae816SLluís Vilanova assert(pat != NULL); 67b1bae816SLluís Vilanova 68b1bae816SLluís Vilanova TraceEventID i; 69b1bae816SLluís Vilanova 70b1bae816SLluís Vilanova if (ev == NULL) { 71b1bae816SLluís Vilanova i = -1; 72b1bae816SLluís Vilanova } else { 73b1bae816SLluís Vilanova i = trace_event_get_id(ev); 74b1bae816SLluís Vilanova } 75b1bae816SLluís Vilanova i++; 76b1bae816SLluís Vilanova 77b1bae816SLluís Vilanova while (i < trace_event_count()) { 78b1bae816SLluís Vilanova TraceEvent *res = trace_event_id(i); 79b1bae816SLluís Vilanova if (pattern_glob(pat, trace_event_get_name(res))) { 80b1bae816SLluís Vilanova return res; 81b1bae816SLluís Vilanova } 82b1bae816SLluís Vilanova i++; 83b1bae816SLluís Vilanova } 84b1bae816SLluís Vilanova 85b1bae816SLluís Vilanova return NULL; 86b1bae816SLluís Vilanova } 87b1bae816SLluís Vilanova 885b808275SLluís Vilanova void trace_print_events(FILE *stream, fprintf_function stream_printf) 895b808275SLluís Vilanova { 905b808275SLluís Vilanova TraceEventID i; 915b808275SLluís Vilanova 925b808275SLluís Vilanova for (i = 0; i < trace_event_count(); i++) { 935b808275SLluís Vilanova TraceEvent *ev = trace_event_id(i); 945b808275SLluís Vilanova stream_printf(stream, "%s [Event ID %u] : state %u\n", 955b808275SLluís Vilanova trace_event_get_name(ev), i, 965b808275SLluís Vilanova trace_event_get_state_static(ev) && 975b808275SLluís Vilanova trace_event_get_state_dynamic(ev)); 985b808275SLluís Vilanova } 995b808275SLluís Vilanova } 1005b808275SLluís Vilanova 1015b808275SLluís Vilanova static void trace_init_events(const char *fname) 10223d15e86SLluís { 103*a35d9be6SAlexey Kardashevskiy Location loc; 104*a35d9be6SAlexey Kardashevskiy FILE *fp; 105*a35d9be6SAlexey Kardashevskiy char line_buf[1024]; 106*a35d9be6SAlexey Kardashevskiy size_t line_idx = 0; 107*a35d9be6SAlexey Kardashevskiy 10823d15e86SLluís if (fname == NULL) { 10923d15e86SLluís return; 11023d15e86SLluís } 11123d15e86SLluís 112*a35d9be6SAlexey Kardashevskiy loc_push_none(&loc); 113*a35d9be6SAlexey Kardashevskiy loc_set_file(fname, 0); 114*a35d9be6SAlexey Kardashevskiy fp = fopen(fname, "r"); 11523d15e86SLluís if (!fp) { 116*a35d9be6SAlexey Kardashevskiy error_report("%s", strerror(errno)); 11723d15e86SLluís exit(1); 11823d15e86SLluís } 11923d15e86SLluís while (fgets(line_buf, sizeof(line_buf), fp)) { 120*a35d9be6SAlexey Kardashevskiy loc_set_file(fname, ++line_idx); 12123d15e86SLluís size_t len = strlen(line_buf); 12223d15e86SLluís if (len > 1) { /* skip empty lines */ 12323d15e86SLluís line_buf[len - 1] = '\0'; 124794b1f96SAlexey Kardashevskiy if ('#' == line_buf[0]) { /* skip commented lines */ 125794b1f96SAlexey Kardashevskiy continue; 126794b1f96SAlexey Kardashevskiy } 127b1bae816SLluís Vilanova const bool enable = ('-' != line_buf[0]); 128b1bae816SLluís Vilanova char *line_ptr = enable ? line_buf : line_buf + 1; 129b1bae816SLluís Vilanova if (trace_event_is_pattern(line_ptr)) { 130b1bae816SLluís Vilanova TraceEvent *ev = NULL; 131b1bae816SLluís Vilanova while ((ev = trace_event_pattern(line_ptr, ev)) != NULL) { 132b1bae816SLluís Vilanova if (trace_event_get_state_static(ev)) { 133b1bae816SLluís Vilanova trace_event_set_state_dynamic(ev, enable); 134ddde8accSGerd Hoffmann } 135b1bae816SLluís Vilanova } 136b1bae816SLluís Vilanova } else { 137b1bae816SLluís Vilanova TraceEvent *ev = trace_event_name(line_ptr); 138b1bae816SLluís Vilanova if (ev == NULL) { 139*a35d9be6SAlexey Kardashevskiy error_report("WARNING: trace event '%s' does not exist", 14082432638SAlexey Kardashevskiy line_ptr); 14182432638SAlexey Kardashevskiy } else if (!trace_event_get_state_static(ev)) { 142*a35d9be6SAlexey Kardashevskiy error_report("WARNING: trace event '%s' is not traceable\n", 14382432638SAlexey Kardashevskiy line_ptr); 14482432638SAlexey Kardashevskiy } else { 145b1bae816SLluís Vilanova trace_event_set_state_dynamic(ev, enable); 146b1bae816SLluís Vilanova } 14723d15e86SLluís } 14823d15e86SLluís } 14982432638SAlexey Kardashevskiy } 15023d15e86SLluís if (fclose(fp) != 0) { 151*a35d9be6SAlexey Kardashevskiy loc_set_file(fname, 0); 152*a35d9be6SAlexey Kardashevskiy error_report("%s", strerror(errno)); 15323d15e86SLluís exit(1); 15423d15e86SLluís } 155*a35d9be6SAlexey Kardashevskiy loc_pop(&loc); 15623d15e86SLluís } 1575b808275SLluís Vilanova 1585b808275SLluís Vilanova bool trace_init_backends(const char *events, const char *file) 1595b808275SLluís Vilanova { 1605b808275SLluís Vilanova #ifdef CONFIG_TRACE_SIMPLE 1615b808275SLluís Vilanova if (!st_init(file)) { 1625b808275SLluís Vilanova fprintf(stderr, "failed to initialize simple tracing backend.\n"); 1635b808275SLluís Vilanova return false; 1645b808275SLluís Vilanova } 1655b808275SLluís Vilanova #else 1665b808275SLluís Vilanova if (file) { 1675b808275SLluís Vilanova fprintf(stderr, "error: -trace file=...: " 1685b808275SLluís Vilanova "option not supported by the selected tracing backends\n"); 1695b808275SLluís Vilanova return false; 1705b808275SLluís Vilanova } 1715b808275SLluís Vilanova #endif 1725b808275SLluís Vilanova 1735b808275SLluís Vilanova #ifdef CONFIG_TRACE_FTRACE 1745b808275SLluís Vilanova if (!ftrace_init()) { 1755b808275SLluís Vilanova fprintf(stderr, "failed to initialize ftrace backend.\n"); 1765b808275SLluís Vilanova return false; 1775b808275SLluís Vilanova } 1785b808275SLluís Vilanova #endif 1795b808275SLluís Vilanova 1805b808275SLluís Vilanova trace_init_events(events); 1815b808275SLluís Vilanova return true; 1825b808275SLluís Vilanova } 183