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