xref: /openbmc/linux/tools/perf/util/debug.c (revision 7587eb18)
1 /* For general debugging purposes */
2 
3 #include "../perf.h"
4 
5 #include <string.h>
6 #include <stdarg.h>
7 #include <stdio.h>
8 #include <api/debug.h>
9 
10 #include "cache.h"
11 #include "color.h"
12 #include "event.h"
13 #include "debug.h"
14 #include "util.h"
15 #include "target.h"
16 
17 #define NSECS_PER_SEC  1000000000ULL
18 #define NSECS_PER_USEC 1000ULL
19 
20 int verbose;
21 bool dump_trace = false, quiet = false;
22 int debug_ordered_events;
23 static int redirect_to_stderr;
24 int debug_data_convert;
25 
26 int veprintf(int level, int var, const char *fmt, va_list args)
27 {
28 	int ret = 0;
29 
30 	if (var >= level) {
31 		if (use_browser >= 1 && !redirect_to_stderr)
32 			ui_helpline__vshow(fmt, args);
33 		else
34 			ret = vfprintf(stderr, fmt, args);
35 	}
36 
37 	return ret;
38 }
39 
40 int eprintf(int level, int var, const char *fmt, ...)
41 {
42 	va_list args;
43 	int ret;
44 
45 	va_start(args, fmt);
46 	ret = veprintf(level, var, fmt, args);
47 	va_end(args);
48 
49 	return ret;
50 }
51 
52 static int veprintf_time(u64 t, const char *fmt, va_list args)
53 {
54 	int ret = 0;
55 	u64 secs, usecs, nsecs = t;
56 
57 	secs   = nsecs / NSECS_PER_SEC;
58 	nsecs -= secs  * NSECS_PER_SEC;
59 	usecs  = nsecs / NSECS_PER_USEC;
60 
61 	ret = fprintf(stderr, "[%13" PRIu64 ".%06" PRIu64 "] ",
62 		      secs, usecs);
63 	ret += vfprintf(stderr, fmt, args);
64 	return ret;
65 }
66 
67 int eprintf_time(int level, int var, u64 t, const char *fmt, ...)
68 {
69 	int ret = 0;
70 	va_list args;
71 
72 	if (var >= level) {
73 		va_start(args, fmt);
74 		ret = veprintf_time(t, fmt, args);
75 		va_end(args);
76 	}
77 
78 	return ret;
79 }
80 
81 /*
82  * Overloading libtraceevent standard info print
83  * function, display with -v in perf.
84  */
85 void pr_stat(const char *fmt, ...)
86 {
87 	va_list args;
88 
89 	va_start(args, fmt);
90 	veprintf(1, verbose, fmt, args);
91 	va_end(args);
92 	eprintf(1, verbose, "\n");
93 }
94 
95 int dump_printf(const char *fmt, ...)
96 {
97 	va_list args;
98 	int ret = 0;
99 
100 	if (dump_trace) {
101 		va_start(args, fmt);
102 		ret = vprintf(fmt, args);
103 		va_end(args);
104 	}
105 
106 	return ret;
107 }
108 
109 static void trace_event_printer(enum binary_printer_ops op,
110 				unsigned int val, void *extra)
111 {
112 	const char *color = PERF_COLOR_BLUE;
113 	union perf_event *event = (union perf_event *)extra;
114 	unsigned char ch = (unsigned char)val;
115 
116 	switch (op) {
117 	case BINARY_PRINT_DATA_BEGIN:
118 		printf(".");
119 		color_fprintf(stdout, color, "\n. ... raw event: size %d bytes\n",
120 				event->header.size);
121 		break;
122 	case BINARY_PRINT_LINE_BEGIN:
123 		printf(".");
124 		break;
125 	case BINARY_PRINT_ADDR:
126 		color_fprintf(stdout, color, "  %04x: ", val);
127 		break;
128 	case BINARY_PRINT_NUM_DATA:
129 		color_fprintf(stdout, color, " %02x", val);
130 		break;
131 	case BINARY_PRINT_NUM_PAD:
132 		color_fprintf(stdout, color, "   ");
133 		break;
134 	case BINARY_PRINT_SEP:
135 		color_fprintf(stdout, color, "  ");
136 		break;
137 	case BINARY_PRINT_CHAR_DATA:
138 		color_fprintf(stdout, color, "%c",
139 			      isprint(ch) ? ch : '.');
140 		break;
141 	case BINARY_PRINT_CHAR_PAD:
142 		color_fprintf(stdout, color, " ");
143 		break;
144 	case BINARY_PRINT_LINE_END:
145 		color_fprintf(stdout, color, "\n");
146 		break;
147 	case BINARY_PRINT_DATA_END:
148 		printf("\n");
149 		break;
150 	default:
151 		break;
152 	}
153 }
154 
155 void trace_event(union perf_event *event)
156 {
157 	unsigned char *raw_event = (void *)event;
158 
159 	if (!dump_trace)
160 		return;
161 
162 	print_binary(raw_event, event->header.size, 16,
163 		     trace_event_printer, event);
164 }
165 
166 static struct debug_variable {
167 	const char *name;
168 	int *ptr;
169 } debug_variables[] = {
170 	{ .name = "verbose",		.ptr = &verbose },
171 	{ .name = "ordered-events",	.ptr = &debug_ordered_events},
172 	{ .name = "stderr",		.ptr = &redirect_to_stderr},
173 	{ .name = "data-convert",	.ptr = &debug_data_convert },
174 	{ .name = NULL, }
175 };
176 
177 int perf_debug_option(const char *str)
178 {
179 	struct debug_variable *var = &debug_variables[0];
180 	char *vstr, *s = strdup(str);
181 	int v = 1;
182 
183 	vstr = strchr(s, '=');
184 	if (vstr)
185 		*vstr++ = 0;
186 
187 	while (var->name) {
188 		if (!strcmp(s, var->name))
189 			break;
190 		var++;
191 	}
192 
193 	if (!var->name) {
194 		pr_err("Unknown debug variable name '%s'\n", s);
195 		free(s);
196 		return -1;
197 	}
198 
199 	if (vstr) {
200 		v = atoi(vstr);
201 		/*
202 		 * Allow only values in range (0, 10),
203 		 * otherwise set 0.
204 		 */
205 		v = (v < 0) || (v > 10) ? 0 : v;
206 	}
207 
208 	*var->ptr = v;
209 	free(s);
210 	return 0;
211 }
212 
213 #define DEBUG_WRAPPER(__n, __l)				\
214 static int pr_ ## __n ## _wrapper(const char *fmt, ...)	\
215 {							\
216 	va_list args;					\
217 	int ret;					\
218 							\
219 	va_start(args, fmt);				\
220 	ret = veprintf(__l, verbose, fmt, args);	\
221 	va_end(args);					\
222 	return ret;					\
223 }
224 
225 DEBUG_WRAPPER(warning, 0);
226 DEBUG_WRAPPER(debug, 1);
227 
228 void perf_debug_setup(void)
229 {
230 	libapi_set_print(pr_warning_wrapper, pr_warning_wrapper, pr_debug_wrapper);
231 }
232