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