1 // SPDX-License-Identifier: GPL-2.0
2 /* For general debugging purposes */
10 #include <api/debug.h>
11 #include <linux/kernel.h>
12 #include <linux/time64.h>
14 #ifdef HAVE_BACKTRACE_SUPPORT
20 #include "print_binary.h"
22 #include "trace-event.h"
23 #include "ui/helpline.h"
25 #include "util/parse-sublevel-options.h"
27 #include <linux/ctype.h>
29 #ifdef HAVE_LIBTRACEEVENT
30 #include <event-parse.h>
32 #define LIBTRACEEVENT_VERSION 0
38 bool dump_trace
= false, quiet
= false;
39 int debug_ordered_events
;
40 static int redirect_to_stderr
;
41 int debug_data_convert
;
42 static FILE *_debug_file
;
43 bool debug_display_time
;
44 int debug_type_profile
;
46 FILE *debug_file(void)
49 pr_warning_once("debug_file not set");
50 debug_set_file(stderr
);
55 void debug_set_file(FILE *file
)
60 void debug_set_display_time(bool set
)
62 debug_display_time
= set
;
65 static int fprintf_time(FILE *file
)
71 if (!debug_display_time
)
74 if (gettimeofday(&tod
, NULL
) != 0)
77 if (localtime_r(&tod
.tv_sec
, <ime
) == NULL
)
80 strftime(date
, sizeof(date
), "%F %H:%M:%S", <ime
);
81 return fprintf(file
, "[%s.%06lu] ", date
, (long)tod
.tv_usec
);
84 int veprintf(int level
, int var
, const char *fmt
, va_list args
)
89 if (use_browser
>= 1 && !redirect_to_stderr
) {
90 ui_helpline__vshow(fmt
, args
);
92 ret
= fprintf_time(debug_file());
93 ret
+= vfprintf(debug_file(), fmt
, args
);
100 int eprintf(int level
, int var
, const char *fmt
, ...)
106 ret
= veprintf(level
, var
, fmt
, args
);
112 static int veprintf_time(u64 t
, const char *fmt
, va_list args
)
115 u64 secs
, usecs
, nsecs
= t
;
117 secs
= nsecs
/ NSEC_PER_SEC
;
118 nsecs
-= secs
* NSEC_PER_SEC
;
119 usecs
= nsecs
/ NSEC_PER_USEC
;
121 ret
= fprintf(debug_file(), "[%13" PRIu64
".%06" PRIu64
"] ", secs
, usecs
);
122 ret
+= vfprintf(debug_file(), fmt
, args
);
126 int eprintf_time(int level
, int var
, u64 t
, const char *fmt
, ...)
133 ret
= veprintf_time(t
, fmt
, args
);
141 * Overloading libtraceevent standard info print
142 * function, display with -v in perf.
144 void pr_stat(const char *fmt
, ...)
149 veprintf(1, verbose
, fmt
, args
);
151 eprintf(1, verbose
, "\n");
154 int dump_printf(const char *fmt
, ...)
161 ret
= vprintf(fmt
, args
);
168 static int trace_event_printer(enum binary_printer_ops op
,
169 unsigned int val
, void *extra
, FILE *fp
)
171 const char *color
= PERF_COLOR_BLUE
;
172 union perf_event
*event
= (union perf_event
*)extra
;
173 unsigned char ch
= (unsigned char)val
;
177 case BINARY_PRINT_DATA_BEGIN
:
178 printed
+= fprintf(fp
, ".");
179 printed
+= color_fprintf(fp
, color
, "\n. ... raw event: size %d bytes\n",
182 case BINARY_PRINT_LINE_BEGIN
:
183 printed
+= fprintf(fp
, ".");
185 case BINARY_PRINT_ADDR
:
186 printed
+= color_fprintf(fp
, color
, " %04x: ", val
);
188 case BINARY_PRINT_NUM_DATA
:
189 printed
+= color_fprintf(fp
, color
, " %02x", val
);
191 case BINARY_PRINT_NUM_PAD
:
192 printed
+= color_fprintf(fp
, color
, " ");
194 case BINARY_PRINT_SEP
:
195 printed
+= color_fprintf(fp
, color
, " ");
197 case BINARY_PRINT_CHAR_DATA
:
198 printed
+= color_fprintf(fp
, color
, "%c",
199 isprint(ch
) && isascii(ch
) ? ch
: '.');
201 case BINARY_PRINT_CHAR_PAD
:
202 printed
+= color_fprintf(fp
, color
, " ");
204 case BINARY_PRINT_LINE_END
:
205 printed
+= color_fprintf(fp
, color
, "\n");
207 case BINARY_PRINT_DATA_END
:
208 printed
+= fprintf(fp
, "\n");
217 void trace_event(union perf_event
*event
)
219 unsigned char *raw_event
= (void *)event
;
224 print_binary(raw_event
, event
->header
.size
, 16,
225 trace_event_printer
, event
);
228 static struct sublevel_option debug_opts
[] = {
229 { .name
= "verbose", .value_ptr
= &verbose
},
230 { .name
= "ordered-events", .value_ptr
= &debug_ordered_events
},
231 { .name
= "stderr", .value_ptr
= &redirect_to_stderr
},
232 { .name
= "data-convert", .value_ptr
= &debug_data_convert
},
233 { .name
= "perf-event-open", .value_ptr
= &debug_peo_args
},
234 { .name
= "kmaps", .value_ptr
= &debug_kmaps
},
235 { .name
= "type-profile", .value_ptr
= &debug_type_profile
},
239 int perf_debug_option(const char *str
)
243 ret
= perf_parse_sublevel_options(str
, debug_opts
);
247 /* Allow only verbose value in range (0, 10), otherwise set 0. */
248 verbose
= (verbose
< 0) || (verbose
> 10) ? 0 : verbose
;
250 #if LIBTRACEEVENT_VERSION >= MAKE_LIBTRACEEVENT_VERSION(1, 3, 0)
252 tep_set_loglevel(TEP_LOG_INFO
);
253 else if (verbose
== 2)
254 tep_set_loglevel(TEP_LOG_DEBUG
);
255 else if (verbose
>= 3)
256 tep_set_loglevel(TEP_LOG_ALL
);
261 int perf_quiet_option(void)
263 struct sublevel_option
*opt
= &debug_opts
[0];
265 /* disable all debug messages */
267 *opt
->value_ptr
= -1;
271 /* For debug variables that are used as bool types, set to 0. */
272 redirect_to_stderr
= 0;
275 debug_type_profile
= 0;
280 #define DEBUG_WRAPPER(__n, __l) \
281 static int pr_ ## __n ## _wrapper(const char *fmt, ...) \
286 va_start(args, fmt); \
287 ret = veprintf(__l, verbose, fmt, args); \
292 DEBUG_WRAPPER(warning
, 0);
293 DEBUG_WRAPPER(debug
, 1);
295 void perf_debug_setup(void)
297 debug_set_file(stderr
);
298 libapi_set_print(pr_warning_wrapper
, pr_warning_wrapper
, pr_debug_wrapper
);
301 /* Obtain a backtrace and print it to stdout. */
302 #ifdef HAVE_BACKTRACE_SUPPORT
303 void dump_stack(void)
306 size_t size
= backtrace(array
, ARRAY_SIZE(array
));
307 char **strings
= backtrace_symbols(array
, size
);
310 printf("Obtained %zd stack frames.\n", size
);
312 for (i
= 0; i
< size
; i
++)
313 printf("%s\n", strings
[i
]);
318 void dump_stack(void) {}
321 void sighandler_dump_stack(int sig
)
323 psignal(sig
, "perf");
325 signal(sig
, SIG_DFL
);