1 /* For general debugging purposes */ 2 3 #include "../perf.h" 4 5 #include <inttypes.h> 6 #include <string.h> 7 #include <stdarg.h> 8 #include <stdio.h> 9 #include <api/debug.h> 10 #include <linux/time64.h> 11 12 #include "cache.h" 13 #include "color.h" 14 #include "event.h" 15 #include "debug.h" 16 #include "util.h" 17 #include "target.h" 18 19 #include "sane_ctype.h" 20 21 int verbose; 22 bool dump_trace = false, quiet = false; 23 int debug_ordered_events; 24 static int redirect_to_stderr; 25 int debug_data_convert; 26 27 int veprintf(int level, int var, const char *fmt, va_list args) 28 { 29 int ret = 0; 30 31 if (var >= level) { 32 if (use_browser >= 1 && !redirect_to_stderr) 33 ui_helpline__vshow(fmt, args); 34 else 35 ret = vfprintf(stderr, fmt, args); 36 } 37 38 return ret; 39 } 40 41 int eprintf(int level, int var, const char *fmt, ...) 42 { 43 va_list args; 44 int ret; 45 46 va_start(args, fmt); 47 ret = veprintf(level, var, fmt, args); 48 va_end(args); 49 50 return ret; 51 } 52 53 static int veprintf_time(u64 t, const char *fmt, va_list args) 54 { 55 int ret = 0; 56 u64 secs, usecs, nsecs = t; 57 58 secs = nsecs / NSEC_PER_SEC; 59 nsecs -= secs * NSEC_PER_SEC; 60 usecs = nsecs / NSEC_PER_USEC; 61 62 ret = fprintf(stderr, "[%13" PRIu64 ".%06" PRIu64 "] ", 63 secs, usecs); 64 ret += vfprintf(stderr, fmt, args); 65 return ret; 66 } 67 68 int eprintf_time(int level, int var, u64 t, const char *fmt, ...) 69 { 70 int ret = 0; 71 va_list args; 72 73 if (var >= level) { 74 va_start(args, fmt); 75 ret = veprintf_time(t, fmt, args); 76 va_end(args); 77 } 78 79 return ret; 80 } 81 82 /* 83 * Overloading libtraceevent standard info print 84 * function, display with -v in perf. 85 */ 86 void pr_stat(const char *fmt, ...) 87 { 88 va_list args; 89 90 va_start(args, fmt); 91 veprintf(1, verbose, fmt, args); 92 va_end(args); 93 eprintf(1, verbose, "\n"); 94 } 95 96 int dump_printf(const char *fmt, ...) 97 { 98 va_list args; 99 int ret = 0; 100 101 if (dump_trace) { 102 va_start(args, fmt); 103 ret = vprintf(fmt, args); 104 va_end(args); 105 } 106 107 return ret; 108 } 109 110 static void trace_event_printer(enum binary_printer_ops op, 111 unsigned int val, void *extra) 112 { 113 const char *color = PERF_COLOR_BLUE; 114 union perf_event *event = (union perf_event *)extra; 115 unsigned char ch = (unsigned char)val; 116 117 switch (op) { 118 case BINARY_PRINT_DATA_BEGIN: 119 printf("."); 120 color_fprintf(stdout, color, "\n. ... raw event: size %d bytes\n", 121 event->header.size); 122 break; 123 case BINARY_PRINT_LINE_BEGIN: 124 printf("."); 125 break; 126 case BINARY_PRINT_ADDR: 127 color_fprintf(stdout, color, " %04x: ", val); 128 break; 129 case BINARY_PRINT_NUM_DATA: 130 color_fprintf(stdout, color, " %02x", val); 131 break; 132 case BINARY_PRINT_NUM_PAD: 133 color_fprintf(stdout, color, " "); 134 break; 135 case BINARY_PRINT_SEP: 136 color_fprintf(stdout, color, " "); 137 break; 138 case BINARY_PRINT_CHAR_DATA: 139 color_fprintf(stdout, color, "%c", 140 isprint(ch) ? ch : '.'); 141 break; 142 case BINARY_PRINT_CHAR_PAD: 143 color_fprintf(stdout, color, " "); 144 break; 145 case BINARY_PRINT_LINE_END: 146 color_fprintf(stdout, color, "\n"); 147 break; 148 case BINARY_PRINT_DATA_END: 149 printf("\n"); 150 break; 151 default: 152 break; 153 } 154 } 155 156 void trace_event(union perf_event *event) 157 { 158 unsigned char *raw_event = (void *)event; 159 160 if (!dump_trace) 161 return; 162 163 print_binary(raw_event, event->header.size, 16, 164 trace_event_printer, event); 165 } 166 167 static struct debug_variable { 168 const char *name; 169 int *ptr; 170 } debug_variables[] = { 171 { .name = "verbose", .ptr = &verbose }, 172 { .name = "ordered-events", .ptr = &debug_ordered_events}, 173 { .name = "stderr", .ptr = &redirect_to_stderr}, 174 { .name = "data-convert", .ptr = &debug_data_convert }, 175 { .name = NULL, } 176 }; 177 178 int perf_debug_option(const char *str) 179 { 180 struct debug_variable *var = &debug_variables[0]; 181 char *vstr, *s = strdup(str); 182 int v = 1; 183 184 vstr = strchr(s, '='); 185 if (vstr) 186 *vstr++ = 0; 187 188 while (var->name) { 189 if (!strcmp(s, var->name)) 190 break; 191 var++; 192 } 193 194 if (!var->name) { 195 pr_err("Unknown debug variable name '%s'\n", s); 196 free(s); 197 return -1; 198 } 199 200 if (vstr) { 201 v = atoi(vstr); 202 /* 203 * Allow only values in range (0, 10), 204 * otherwise set 0. 205 */ 206 v = (v < 0) || (v > 10) ? 0 : v; 207 } 208 209 if (quiet) 210 v = -1; 211 212 *var->ptr = v; 213 free(s); 214 return 0; 215 } 216 217 int perf_quiet_option(void) 218 { 219 struct debug_variable *var = &debug_variables[0]; 220 221 /* disable all debug messages */ 222 while (var->name) { 223 *var->ptr = -1; 224 var++; 225 } 226 227 quiet = true; 228 return 0; 229 } 230 231 #define DEBUG_WRAPPER(__n, __l) \ 232 static int pr_ ## __n ## _wrapper(const char *fmt, ...) \ 233 { \ 234 va_list args; \ 235 int ret; \ 236 \ 237 va_start(args, fmt); \ 238 ret = veprintf(__l, verbose, fmt, args); \ 239 va_end(args); \ 240 return ret; \ 241 } 242 243 DEBUG_WRAPPER(warning, 0); 244 DEBUG_WRAPPER(debug, 1); 245 246 void perf_debug_setup(void) 247 { 248 libapi_set_print(pr_warning_wrapper, pr_warning_wrapper, pr_debug_wrapper); 249 } 250