1 /* 2 * Interface for configuring and controlling the state of tracing events. 3 * 4 * Copyright (C) 2011-2014 Lluís Vilanova <vilanova@ac.upc.edu> 5 * 6 * This work is licensed under the terms of the GNU GPL, version 2 or later. 7 * See the COPYING file in the top-level directory. 8 */ 9 10 #include "trace/control.h" 11 #ifdef CONFIG_TRACE_SIMPLE 12 #include "trace/simple.h" 13 #endif 14 #ifdef CONFIG_TRACE_FTRACE 15 #include "trace/ftrace.h" 16 #endif 17 #include "qemu/error-report.h" 18 19 TraceEvent *trace_event_name(const char *name) 20 { 21 assert(name != NULL); 22 23 TraceEventID i; 24 for (i = 0; i < trace_event_count(); i++) { 25 TraceEvent *ev = trace_event_id(i); 26 if (strcmp(trace_event_get_name(ev), name) == 0) { 27 return ev; 28 } 29 } 30 return NULL; 31 } 32 33 static bool pattern_glob(const char *pat, const char *ev) 34 { 35 while (*pat != '\0' && *ev != '\0') { 36 if (*pat == *ev) { 37 pat++; 38 ev++; 39 } 40 else if (*pat == '*') { 41 if (pattern_glob(pat, ev+1)) { 42 return true; 43 } else if (pattern_glob(pat+1, ev)) { 44 return true; 45 } else { 46 return false; 47 } 48 } else { 49 return false; 50 } 51 } 52 53 while (*pat == '*') { 54 pat++; 55 } 56 57 if (*pat == '\0' && *ev == '\0') { 58 return true; 59 } else { 60 return false; 61 } 62 } 63 64 TraceEvent *trace_event_pattern(const char *pat, TraceEvent *ev) 65 { 66 assert(pat != NULL); 67 68 TraceEventID i; 69 70 if (ev == NULL) { 71 i = -1; 72 } else { 73 i = trace_event_get_id(ev); 74 } 75 i++; 76 77 while (i < trace_event_count()) { 78 TraceEvent *res = trace_event_id(i); 79 if (pattern_glob(pat, trace_event_get_name(res))) { 80 return res; 81 } 82 i++; 83 } 84 85 return NULL; 86 } 87 88 void trace_print_events(FILE *stream, fprintf_function stream_printf) 89 { 90 TraceEventID i; 91 92 for (i = 0; i < trace_event_count(); i++) { 93 TraceEvent *ev = trace_event_id(i); 94 stream_printf(stream, "%s [Event ID %u] : state %u\n", 95 trace_event_get_name(ev), i, 96 trace_event_get_state_static(ev) && 97 trace_event_get_state_dynamic(ev)); 98 } 99 } 100 101 static void trace_init_events(const char *fname) 102 { 103 Location loc; 104 FILE *fp; 105 char line_buf[1024]; 106 size_t line_idx = 0; 107 108 if (fname == NULL) { 109 return; 110 } 111 112 loc_push_none(&loc); 113 loc_set_file(fname, 0); 114 fp = fopen(fname, "r"); 115 if (!fp) { 116 error_report("%s", strerror(errno)); 117 exit(1); 118 } 119 while (fgets(line_buf, sizeof(line_buf), fp)) { 120 loc_set_file(fname, ++line_idx); 121 size_t len = strlen(line_buf); 122 if (len > 1) { /* skip empty lines */ 123 line_buf[len - 1] = '\0'; 124 if ('#' == line_buf[0]) { /* skip commented lines */ 125 continue; 126 } 127 const bool enable = ('-' != line_buf[0]); 128 char *line_ptr = enable ? line_buf : line_buf + 1; 129 if (trace_event_is_pattern(line_ptr)) { 130 TraceEvent *ev = NULL; 131 while ((ev = trace_event_pattern(line_ptr, ev)) != NULL) { 132 if (trace_event_get_state_static(ev)) { 133 trace_event_set_state_dynamic(ev, enable); 134 } 135 } 136 } else { 137 TraceEvent *ev = trace_event_name(line_ptr); 138 if (ev == NULL) { 139 error_report("WARNING: trace event '%s' does not exist", 140 line_ptr); 141 } else if (!trace_event_get_state_static(ev)) { 142 error_report("WARNING: trace event '%s' is not traceable\n", 143 line_ptr); 144 } else { 145 trace_event_set_state_dynamic(ev, enable); 146 } 147 } 148 } 149 } 150 if (fclose(fp) != 0) { 151 loc_set_file(fname, 0); 152 error_report("%s", strerror(errno)); 153 exit(1); 154 } 155 loc_pop(&loc); 156 } 157 158 bool trace_init_backends(const char *events, const char *file) 159 { 160 #ifdef CONFIG_TRACE_SIMPLE 161 if (!st_init(file)) { 162 fprintf(stderr, "failed to initialize simple tracing backend.\n"); 163 return false; 164 } 165 #else 166 if (file) { 167 fprintf(stderr, "error: -trace file=...: " 168 "option not supported by the selected tracing backends\n"); 169 return false; 170 } 171 #endif 172 173 #ifdef CONFIG_TRACE_FTRACE 174 if (!ftrace_init()) { 175 fprintf(stderr, "failed to initialize ftrace backend.\n"); 176 return false; 177 } 178 #endif 179 180 trace_init_events(events); 181 return true; 182 } 183