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