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