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