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