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