1/* For general debugging purposes */
2
3#include "../perf.h"
4
5#include <string.h>
6#include <stdarg.h>
7#include <stdio.h>
8
9#include "cache.h"
10#include "color.h"
11#include "event.h"
12#include "debug.h"
13#include "util.h"
14#include "target.h"
15
16#define NSECS_PER_SEC  1000000000ULL
17#define NSECS_PER_USEC 1000ULL
18
19int verbose;
20bool dump_trace = false, quiet = false;
21int debug_ordered_events;
22static int redirect_to_stderr;
23int debug_data_convert;
24
25static int _eprintf(int level, int var, const char *fmt, va_list args)
26{
27	int ret = 0;
28
29	if (var >= level) {
30		if (use_browser >= 1 && !redirect_to_stderr)
31			ui_helpline__vshow(fmt, args);
32		else
33			ret = vfprintf(stderr, fmt, args);
34	}
35
36	return ret;
37}
38
39int eprintf(int level, int var, const char *fmt, ...)
40{
41	va_list args;
42	int ret;
43
44	va_start(args, fmt);
45	ret = _eprintf(level, var, fmt, args);
46	va_end(args);
47
48	return ret;
49}
50
51static int __eprintf_time(u64 t, const char *fmt, va_list args)
52{
53	int ret = 0;
54	u64 secs, usecs, nsecs = t;
55
56	secs   = nsecs / NSECS_PER_SEC;
57	nsecs -= secs  * NSECS_PER_SEC;
58	usecs  = nsecs / NSECS_PER_USEC;
59
60	ret = fprintf(stderr, "[%13" PRIu64 ".%06" PRIu64 "] ",
61		      secs, usecs);
62	ret += vfprintf(stderr, fmt, args);
63	return ret;
64}
65
66int eprintf_time(int level, int var, u64 t, const char *fmt, ...)
67{
68	int ret = 0;
69	va_list args;
70
71	if (var >= level) {
72		va_start(args, fmt);
73		ret = __eprintf_time(t, fmt, args);
74		va_end(args);
75	}
76
77	return ret;
78}
79
80/*
81 * Overloading libtraceevent standard info print
82 * function, display with -v in perf.
83 */
84void pr_stat(const char *fmt, ...)
85{
86	va_list args;
87
88	va_start(args, fmt);
89	_eprintf(1, verbose, fmt, args);
90	va_end(args);
91	eprintf(1, verbose, "\n");
92}
93
94int dump_printf(const char *fmt, ...)
95{
96	va_list args;
97	int ret = 0;
98
99	if (dump_trace) {
100		va_start(args, fmt);
101		ret = vprintf(fmt, args);
102		va_end(args);
103	}
104
105	return ret;
106}
107
108void trace_event(union perf_event *event)
109{
110	unsigned char *raw_event = (void *)event;
111	const char *color = PERF_COLOR_BLUE;
112	int i, j;
113
114	if (!dump_trace)
115		return;
116
117	printf(".");
118	color_fprintf(stdout, color, "\n. ... raw event: size %d bytes\n",
119		      event->header.size);
120
121	for (i = 0; i < event->header.size; i++) {
122		if ((i & 15) == 0) {
123			printf(".");
124			color_fprintf(stdout, color, "  %04x: ", i);
125		}
126
127		color_fprintf(stdout, color, " %02x", raw_event[i]);
128
129		if (((i & 15) == 15) || i == event->header.size-1) {
130			color_fprintf(stdout, color, "  ");
131			for (j = 0; j < 15-(i & 15); j++)
132				color_fprintf(stdout, color, "   ");
133			for (j = i & ~15; j <= i; j++) {
134				color_fprintf(stdout, color, "%c",
135					      isprint(raw_event[j]) ?
136					      raw_event[j] : '.');
137			}
138			color_fprintf(stdout, color, "\n");
139		}
140	}
141	printf(".\n");
142}
143
144static struct debug_variable {
145	const char *name;
146	int *ptr;
147} debug_variables[] = {
148	{ .name = "verbose",		.ptr = &verbose },
149	{ .name = "ordered-events",	.ptr = &debug_ordered_events},
150	{ .name = "stderr",		.ptr = &redirect_to_stderr},
151	{ .name = "data-convert",	.ptr = &debug_data_convert },
152	{ .name = NULL, }
153};
154
155int perf_debug_option(const char *str)
156{
157	struct debug_variable *var = &debug_variables[0];
158	char *vstr, *s = strdup(str);
159	int v = 1;
160
161	vstr = strchr(s, '=');
162	if (vstr)
163		*vstr++ = 0;
164
165	while (var->name) {
166		if (!strcmp(s, var->name))
167			break;
168		var++;
169	}
170
171	if (!var->name) {
172		pr_err("Unknown debug variable name '%s'\n", s);
173		free(s);
174		return -1;
175	}
176
177	if (vstr) {
178		v = atoi(vstr);
179		/*
180		 * Allow only values in range (0, 10),
181		 * otherwise set 0.
182		 */
183		v = (v < 0) || (v > 10) ? 0 : v;
184	}
185
186	*var->ptr = v;
187	free(s);
188	return 0;
189}
190