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_init_events(const char *fname) 92 { 93 Location loc; 94 FILE *fp; 95 char line_buf[1024]; 96 size_t line_idx = 0; 97 98 if (fname == NULL) { 99 return; 100 } 101 102 loc_push_none(&loc); 103 loc_set_file(fname, 0); 104 fp = fopen(fname, "r"); 105 if (!fp) { 106 error_report("%s", strerror(errno)); 107 exit(1); 108 } 109 while (fgets(line_buf, sizeof(line_buf), fp)) { 110 loc_set_file(fname, ++line_idx); 111 size_t len = strlen(line_buf); 112 if (len > 1) { /* skip empty lines */ 113 line_buf[len - 1] = '\0'; 114 if ('#' == line_buf[0]) { /* skip commented lines */ 115 continue; 116 } 117 const bool enable = ('-' != line_buf[0]); 118 char *line_ptr = enable ? line_buf : line_buf + 1; 119 if (trace_event_is_pattern(line_ptr)) { 120 TraceEvent *ev = NULL; 121 while ((ev = trace_event_pattern(line_ptr, ev)) != NULL) { 122 if (trace_event_get_state_static(ev)) { 123 trace_event_set_state_dynamic(ev, enable); 124 } 125 } 126 } else { 127 TraceEvent *ev = trace_event_name(line_ptr); 128 if (ev == NULL) { 129 error_report("WARNING: trace event '%s' does not exist", 130 line_ptr); 131 } else if (!trace_event_get_state_static(ev)) { 132 error_report("WARNING: trace event '%s' is not traceable", 133 line_ptr); 134 } else { 135 trace_event_set_state_dynamic(ev, enable); 136 } 137 } 138 } 139 } 140 if (fclose(fp) != 0) { 141 loc_set_file(fname, 0); 142 error_report("%s", strerror(errno)); 143 exit(1); 144 } 145 loc_pop(&loc); 146 } 147 148 bool trace_init_backends(const char *file) 149 { 150 #ifdef CONFIG_TRACE_SIMPLE 151 if (!st_init(file)) { 152 fprintf(stderr, "failed to initialize simple tracing backend.\n"); 153 return false; 154 } 155 #else 156 if (file) { 157 fprintf(stderr, "error: -trace file=...: " 158 "option not supported by the selected tracing backends\n"); 159 return false; 160 } 161 #endif 162 163 #ifdef CONFIG_TRACE_FTRACE 164 if (!ftrace_init()) { 165 fprintf(stderr, "failed to initialize ftrace backend.\n"); 166 return false; 167 } 168 #endif 169 170 return true; 171 } 172