0001
0002
0003
0004 #include <inttypes.h>
0005 #include <string.h>
0006 #include <stdarg.h>
0007 #include <stdio.h>
0008 #include <stdlib.h>
0009 #include <sys/wait.h>
0010 #include <api/debug.h>
0011 #include <linux/kernel.h>
0012 #include <linux/time64.h>
0013 #include <sys/time.h>
0014 #ifdef HAVE_BACKTRACE_SUPPORT
0015 #include <execinfo.h>
0016 #endif
0017 #include "color.h"
0018 #include "event.h"
0019 #include "debug.h"
0020 #include "print_binary.h"
0021 #include "target.h"
0022 #include "ui/helpline.h"
0023 #include "ui/ui.h"
0024 #include "util/parse-sublevel-options.h"
0025
0026 #include <linux/ctype.h>
0027
0028 int verbose;
0029 int debug_peo_args;
0030 bool dump_trace = false, quiet = false;
0031 int debug_ordered_events;
0032 static int redirect_to_stderr;
0033 int debug_data_convert;
0034 static FILE *debug_file;
0035 bool debug_display_time;
0036
0037 void debug_set_file(FILE *file)
0038 {
0039 debug_file = file;
0040 }
0041
0042 void debug_set_display_time(bool set)
0043 {
0044 debug_display_time = set;
0045 }
0046
0047 static int fprintf_time(FILE *file)
0048 {
0049 struct timeval tod;
0050 struct tm ltime;
0051 char date[64];
0052
0053 if (!debug_display_time)
0054 return 0;
0055
0056 if (gettimeofday(&tod, NULL) != 0)
0057 return 0;
0058
0059 if (localtime_r(&tod.tv_sec, <ime) == NULL)
0060 return 0;
0061
0062 strftime(date, sizeof(date), "%F %H:%M:%S", <ime);
0063 return fprintf(file, "[%s.%06lu] ", date, (long)tod.tv_usec);
0064 }
0065
0066 int veprintf(int level, int var, const char *fmt, va_list args)
0067 {
0068 int ret = 0;
0069
0070 if (var >= level) {
0071 if (use_browser >= 1 && !redirect_to_stderr) {
0072 ui_helpline__vshow(fmt, args);
0073 } else {
0074 ret = fprintf_time(debug_file);
0075 ret += vfprintf(debug_file, fmt, args);
0076 }
0077 }
0078
0079 return ret;
0080 }
0081
0082 int eprintf(int level, int var, const char *fmt, ...)
0083 {
0084 va_list args;
0085 int ret;
0086
0087 va_start(args, fmt);
0088 ret = veprintf(level, var, fmt, args);
0089 va_end(args);
0090
0091 return ret;
0092 }
0093
0094 static int veprintf_time(u64 t, const char *fmt, va_list args)
0095 {
0096 int ret = 0;
0097 u64 secs, usecs, nsecs = t;
0098
0099 secs = nsecs / NSEC_PER_SEC;
0100 nsecs -= secs * NSEC_PER_SEC;
0101 usecs = nsecs / NSEC_PER_USEC;
0102
0103 ret = fprintf(stderr, "[%13" PRIu64 ".%06" PRIu64 "] ",
0104 secs, usecs);
0105 ret += vfprintf(stderr, fmt, args);
0106 return ret;
0107 }
0108
0109 int eprintf_time(int level, int var, u64 t, const char *fmt, ...)
0110 {
0111 int ret = 0;
0112 va_list args;
0113
0114 if (var >= level) {
0115 va_start(args, fmt);
0116 ret = veprintf_time(t, fmt, args);
0117 va_end(args);
0118 }
0119
0120 return ret;
0121 }
0122
0123
0124
0125
0126
0127 void pr_stat(const char *fmt, ...)
0128 {
0129 va_list args;
0130
0131 va_start(args, fmt);
0132 veprintf(1, verbose, fmt, args);
0133 va_end(args);
0134 eprintf(1, verbose, "\n");
0135 }
0136
0137 int dump_printf(const char *fmt, ...)
0138 {
0139 va_list args;
0140 int ret = 0;
0141
0142 if (dump_trace) {
0143 va_start(args, fmt);
0144 ret = vprintf(fmt, args);
0145 va_end(args);
0146 }
0147
0148 return ret;
0149 }
0150
0151 static int trace_event_printer(enum binary_printer_ops op,
0152 unsigned int val, void *extra, FILE *fp)
0153 {
0154 const char *color = PERF_COLOR_BLUE;
0155 union perf_event *event = (union perf_event *)extra;
0156 unsigned char ch = (unsigned char)val;
0157 int printed = 0;
0158
0159 switch (op) {
0160 case BINARY_PRINT_DATA_BEGIN:
0161 printed += fprintf(fp, ".");
0162 printed += color_fprintf(fp, color, "\n. ... raw event: size %d bytes\n",
0163 event->header.size);
0164 break;
0165 case BINARY_PRINT_LINE_BEGIN:
0166 printed += fprintf(fp, ".");
0167 break;
0168 case BINARY_PRINT_ADDR:
0169 printed += color_fprintf(fp, color, " %04x: ", val);
0170 break;
0171 case BINARY_PRINT_NUM_DATA:
0172 printed += color_fprintf(fp, color, " %02x", val);
0173 break;
0174 case BINARY_PRINT_NUM_PAD:
0175 printed += color_fprintf(fp, color, " ");
0176 break;
0177 case BINARY_PRINT_SEP:
0178 printed += color_fprintf(fp, color, " ");
0179 break;
0180 case BINARY_PRINT_CHAR_DATA:
0181 printed += color_fprintf(fp, color, "%c",
0182 isprint(ch) && isascii(ch) ? ch : '.');
0183 break;
0184 case BINARY_PRINT_CHAR_PAD:
0185 printed += color_fprintf(fp, color, " ");
0186 break;
0187 case BINARY_PRINT_LINE_END:
0188 printed += color_fprintf(fp, color, "\n");
0189 break;
0190 case BINARY_PRINT_DATA_END:
0191 printed += fprintf(fp, "\n");
0192 break;
0193 default:
0194 break;
0195 }
0196
0197 return printed;
0198 }
0199
0200 void trace_event(union perf_event *event)
0201 {
0202 unsigned char *raw_event = (void *)event;
0203
0204 if (!dump_trace)
0205 return;
0206
0207 print_binary(raw_event, event->header.size, 16,
0208 trace_event_printer, event);
0209 }
0210
0211 static struct sublevel_option debug_opts[] = {
0212 { .name = "verbose", .value_ptr = &verbose },
0213 { .name = "ordered-events", .value_ptr = &debug_ordered_events},
0214 { .name = "stderr", .value_ptr = &redirect_to_stderr},
0215 { .name = "data-convert", .value_ptr = &debug_data_convert },
0216 { .name = "perf-event-open", .value_ptr = &debug_peo_args },
0217 { .name = NULL, }
0218 };
0219
0220 int perf_debug_option(const char *str)
0221 {
0222 int ret;
0223
0224 ret = perf_parse_sublevel_options(str, debug_opts);
0225 if (ret)
0226 return ret;
0227
0228
0229 verbose = (verbose < 0) || (verbose > 10) ? 0 : verbose;
0230
0231 return 0;
0232 }
0233
0234 int perf_quiet_option(void)
0235 {
0236 struct sublevel_option *opt = &debug_opts[0];
0237
0238
0239 while (opt->name) {
0240 *opt->value_ptr = -1;
0241 opt++;
0242 }
0243
0244 return 0;
0245 }
0246
0247 #define DEBUG_WRAPPER(__n, __l) \
0248 static int pr_ ## __n ## _wrapper(const char *fmt, ...) \
0249 { \
0250 va_list args; \
0251 int ret; \
0252 \
0253 va_start(args, fmt); \
0254 ret = veprintf(__l, verbose, fmt, args); \
0255 va_end(args); \
0256 return ret; \
0257 }
0258
0259 DEBUG_WRAPPER(warning, 0);
0260 DEBUG_WRAPPER(debug, 1);
0261
0262 void perf_debug_setup(void)
0263 {
0264 debug_set_file(stderr);
0265 libapi_set_print(pr_warning_wrapper, pr_warning_wrapper, pr_debug_wrapper);
0266 }
0267
0268
0269 #ifdef HAVE_BACKTRACE_SUPPORT
0270 void dump_stack(void)
0271 {
0272 void *array[16];
0273 size_t size = backtrace(array, ARRAY_SIZE(array));
0274 char **strings = backtrace_symbols(array, size);
0275 size_t i;
0276
0277 printf("Obtained %zd stack frames.\n", size);
0278
0279 for (i = 0; i < size; i++)
0280 printf("%s\n", strings[i]);
0281
0282 free(strings);
0283 }
0284 #else
0285 void dump_stack(void) {}
0286 #endif
0287
0288 void sighandler_dump_stack(int sig)
0289 {
0290 psignal(sig, "perf");
0291 dump_stack();
0292 signal(sig, SIG_DFL);
0293 raise(sig);
0294 }