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 int trace_events_enabled_count; 20 bool trace_events_dstate[TRACE_EVENT_COUNT]; 21 22 TraceEvent *trace_event_name(const char *name) 23 { 24 assert(name != NULL); 25 26 TraceEventID i; 27 for (i = 0; i < trace_event_count(); i++) { 28 TraceEvent *ev = trace_event_id(i); 29 if (strcmp(trace_event_get_name(ev), name) == 0) { 30 return ev; 31 } 32 } 33 return NULL; 34 } 35 36 static bool pattern_glob(const char *pat, const char *ev) 37 { 38 while (*pat != '\0' && *ev != '\0') { 39 if (*pat == *ev) { 40 pat++; 41 ev++; 42 } 43 else if (*pat == '*') { 44 if (pattern_glob(pat, ev+1)) { 45 return true; 46 } else if (pattern_glob(pat+1, ev)) { 47 return true; 48 } else { 49 return false; 50 } 51 } else { 52 return false; 53 } 54 } 55 56 while (*pat == '*') { 57 pat++; 58 } 59 60 if (*pat == '\0' && *ev == '\0') { 61 return true; 62 } else { 63 return false; 64 } 65 } 66 67 TraceEvent *trace_event_pattern(const char *pat, TraceEvent *ev) 68 { 69 assert(pat != NULL); 70 71 TraceEventID i; 72 73 if (ev == NULL) { 74 i = -1; 75 } else { 76 i = trace_event_get_id(ev); 77 } 78 i++; 79 80 while (i < trace_event_count()) { 81 TraceEvent *res = trace_event_id(i); 82 if (pattern_glob(pat, trace_event_get_name(res))) { 83 return res; 84 } 85 i++; 86 } 87 88 return NULL; 89 } 90 91 void trace_list_events(void) 92 { 93 int i; 94 for (i = 0; i < trace_event_count(); i++) { 95 TraceEvent *res = trace_event_id(i); 96 fprintf(stderr, "%s\n", trace_event_get_name(res)); 97 } 98 } 99 100 static void do_trace_enable_events(const char *line_buf) 101 { 102 const bool enable = ('-' != line_buf[0]); 103 const char *line_ptr = enable ? line_buf : line_buf + 1; 104 105 if (trace_event_is_pattern(line_ptr)) { 106 TraceEvent *ev = NULL; 107 while ((ev = trace_event_pattern(line_ptr, ev)) != NULL) { 108 if (trace_event_get_state_static(ev)) { 109 trace_event_set_state_dynamic(ev, enable); 110 } 111 } 112 } else { 113 TraceEvent *ev = trace_event_name(line_ptr); 114 if (ev == NULL) { 115 error_report("WARNING: trace event '%s' does not exist", 116 line_ptr); 117 } else if (!trace_event_get_state_static(ev)) { 118 error_report("WARNING: trace event '%s' is not traceable", 119 line_ptr); 120 } else { 121 trace_event_set_state_dynamic(ev, enable); 122 } 123 } 124 } 125 126 void trace_enable_events(const char *line_buf) 127 { 128 if (is_help_option(line_buf)) { 129 trace_list_events(); 130 exit(0); 131 } else { 132 do_trace_enable_events(line_buf); 133 } 134 } 135 136 void trace_init_events(const char *fname) 137 { 138 Location loc; 139 FILE *fp; 140 char line_buf[1024]; 141 size_t line_idx = 0; 142 143 if (fname == NULL) { 144 return; 145 } 146 147 loc_push_none(&loc); 148 loc_set_file(fname, 0); 149 fp = fopen(fname, "r"); 150 if (!fp) { 151 error_report("%s", strerror(errno)); 152 exit(1); 153 } 154 while (fgets(line_buf, sizeof(line_buf), fp)) { 155 loc_set_file(fname, ++line_idx); 156 size_t len = strlen(line_buf); 157 if (len > 1) { /* skip empty lines */ 158 line_buf[len - 1] = '\0'; 159 if ('#' == line_buf[0]) { /* skip commented lines */ 160 continue; 161 } 162 trace_enable_events(line_buf); 163 } 164 } 165 if (fclose(fp) != 0) { 166 loc_set_file(fname, 0); 167 error_report("%s", strerror(errno)); 168 exit(1); 169 } 170 loc_pop(&loc); 171 } 172 173 void trace_init_file(const char *file) 174 { 175 #ifdef CONFIG_TRACE_SIMPLE 176 st_set_trace_file(file); 177 #else 178 if (file) { 179 fprintf(stderr, "error: -trace file=...: " 180 "option not supported by the selected tracing backends\n"); 181 exit(1); 182 } 183 #endif 184 } 185 186 bool trace_init_backends(void) 187 { 188 #ifdef CONFIG_TRACE_SIMPLE 189 if (!st_init()) { 190 fprintf(stderr, "failed to initialize simple tracing backend.\n"); 191 return false; 192 } 193 #endif 194 195 #ifdef CONFIG_TRACE_FTRACE 196 if (!ftrace_init()) { 197 fprintf(stderr, "failed to initialize ftrace backend.\n"); 198 return false; 199 } 200 #endif 201 202 return true; 203 } 204