xref: /netbsd-src/external/cddl/osnet/dev/dtrace/dtrace_debug.c (revision ba2539a9805a0544ff82c0003cc02fe1eee5603d)
1*ba2539a9Schs /*	$NetBSD: dtrace_debug.c,v 1.9 2018/05/28 21:05:03 chs Exp $	*/
201c9547eSdarran 
3bb8023b5Sdarran /*-
4bb8023b5Sdarran  * Copyright (C) 2008 John Birrell <jb@freebsd.org>.
5bb8023b5Sdarran  * All rights reserved.
6bb8023b5Sdarran  *
7bb8023b5Sdarran  * Redistribution and use in source and binary forms, with or without
8bb8023b5Sdarran  * modification, are permitted provided that the following conditions
9bb8023b5Sdarran  * are met:
10bb8023b5Sdarran  * 1. Redistributions of source code must retain the above copyright
11bb8023b5Sdarran  *    notice(s), this list of conditions and the following disclaimer as
12bb8023b5Sdarran  *    the first lines of this file unmodified other than the possible
13bb8023b5Sdarran  *    addition of one or more copyright notices.
14bb8023b5Sdarran  * 2. Redistributions in binary form must reproduce the above copyright
15bb8023b5Sdarran  *    notice(s), this list of conditions and the following disclaimer in the
16bb8023b5Sdarran  *    documentation and/or other materials provided with the distribution.
17bb8023b5Sdarran  *
18bb8023b5Sdarran  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
19bb8023b5Sdarran  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20bb8023b5Sdarran  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21bb8023b5Sdarran  * DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
22bb8023b5Sdarran  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23bb8023b5Sdarran  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24bb8023b5Sdarran  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25bb8023b5Sdarran  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26bb8023b5Sdarran  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27bb8023b5Sdarran  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
28bb8023b5Sdarran  * DAMAGE.
29bb8023b5Sdarran  *
30*ba2539a9Schs  * $FreeBSD: head/sys/cddl/dev/dtrace/dtrace_debug.c 315208 2017-03-13 18:43:00Z markj $
31bb8023b5Sdarran  *
32bb8023b5Sdarran  */
33bb8023b5Sdarran 
3401c9547eSdarran static char const hex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz";
3501c9547eSdarran #define	hex2ascii(hex)	(hex2ascii_data[hex])
36*ba2539a9Schs #define MAXCPU MAXCPUS
3701c9547eSdarran 
38bb8023b5Sdarran #ifdef DEBUG
39bb8023b5Sdarran 
40bb8023b5Sdarran #define DTRACE_DEBUG_BUFR_SIZE	(32 * 1024)
41bb8023b5Sdarran 
42bb8023b5Sdarran struct dtrace_debug_data {
43*ba2539a9Schs 	u_long lock __aligned(CACHE_LINE_SIZE);
44bb8023b5Sdarran 	char bufr[DTRACE_DEBUG_BUFR_SIZE];
45bb8023b5Sdarran 	char *first;
46bb8023b5Sdarran 	char *last;
47bb8023b5Sdarran 	char *next;
48*ba2539a9Schs } dtrace_debug_data[MAXCPU];
49bb8023b5Sdarran 
50bb8023b5Sdarran static char dtrace_debug_bufr[DTRACE_DEBUG_BUFR_SIZE];
51bb8023b5Sdarran 
52bb8023b5Sdarran static void
dtrace_debug_lock(int cpu)5322738551Schs dtrace_debug_lock(int cpu)
54bb8023b5Sdarran {
55*ba2539a9Schs 	void *tid;
56*ba2539a9Schs 
57*ba2539a9Schs 	tid = curlwp;
58*ba2539a9Schs 	while (atomic_cas_ptr(&dtrace_debug_data[cpu].lock, 0, tid) == 0)
59bb8023b5Sdarran 		/* Loop until the lock is obtained. */
60bb8023b5Sdarran 		;
61bb8023b5Sdarran }
62bb8023b5Sdarran 
63bb8023b5Sdarran static void
dtrace_debug_unlock(int cpu)6422738551Schs dtrace_debug_unlock(int cpu)
65bb8023b5Sdarran {
66*ba2539a9Schs 
67*ba2539a9Schs 	membar_producer();
68*ba2539a9Schs 	dtrace_debug_data[cpu].lock = 0;
69bb8023b5Sdarran }
70bb8023b5Sdarran 
71bb8023b5Sdarran static void
dtrace_debug_init(void * dummy)72bb8023b5Sdarran dtrace_debug_init(void *dummy)
73bb8023b5Sdarran {
74bb8023b5Sdarran 	struct dtrace_debug_data *d;
7501c9547eSdarran 	CPU_INFO_ITERATOR cpuind;
7601c9547eSdarran 	struct cpu_info *cinfo;
77bb8023b5Sdarran 
7801c9547eSdarran 	for (CPU_INFO_FOREACH(cpuind, cinfo)) {
7901c9547eSdarran 		d = &dtrace_debug_data[cpu_index(cinfo)];
80bb8023b5Sdarran 
81bb8023b5Sdarran 		if (d->first == NULL) {
82bb8023b5Sdarran 			d->first = d->bufr;
83bb8023b5Sdarran 			d->next = d->bufr;
84bb8023b5Sdarran 			d->last = d->bufr + DTRACE_DEBUG_BUFR_SIZE - 1;
85bb8023b5Sdarran 			*(d->last) = '\0';
86bb8023b5Sdarran 		}
87bb8023b5Sdarran 	}
88bb8023b5Sdarran }
89bb8023b5Sdarran 
90*ba2539a9Schs #ifdef __FreeBSD__
91*ba2539a9Schs SYSINIT(dtrace_debug_init, SI_SUB_KDTRACE, SI_ORDER_ANY, dtrace_debug_init, NULL);
92*ba2539a9Schs SYSINIT(dtrace_debug_smpinit, SI_SUB_SMP, SI_ORDER_ANY, dtrace_debug_init, NULL);
93*ba2539a9Schs #endif
94bb8023b5Sdarran 
95bb8023b5Sdarran static void
dtrace_debug_output(void)96bb8023b5Sdarran dtrace_debug_output(void)
97bb8023b5Sdarran {
98bb8023b5Sdarran 	char *p;
99*ba2539a9Schs 	int i;
100bb8023b5Sdarran 	struct dtrace_debug_data *d;
101bb8023b5Sdarran 	uintptr_t count;
10201c9547eSdarran 	CPU_INFO_ITERATOR cpuind;
10301c9547eSdarran 	struct cpu_info *cinfo;
104bb8023b5Sdarran 
10501c9547eSdarran 	for (CPU_INFO_FOREACH(cpuind, cinfo)) {
106*ba2539a9Schs 	    	i = cpu_index(cinfo);
107*ba2539a9Schs 		dtrace_debug_lock(i);
108bb8023b5Sdarran 
109*ba2539a9Schs 		d = &dtrace_debug_data[i];
110bb8023b5Sdarran 
111bb8023b5Sdarran 		count = 0;
112bb8023b5Sdarran 
113bb8023b5Sdarran 		if (d->first < d->next) {
114bb8023b5Sdarran 			char *p1 = dtrace_debug_bufr;
115bb8023b5Sdarran 
116bb8023b5Sdarran 			count = (uintptr_t) d->next - (uintptr_t) d->first;
117bb8023b5Sdarran 
118bb8023b5Sdarran 			for (p = d->first; p < d->next; p++)
119bb8023b5Sdarran 				*p1++ = *p;
120ad5eab92Sozaki-r 		} else if (d->first > d->next) {
121bb8023b5Sdarran 			char *p1 = dtrace_debug_bufr;
122bb8023b5Sdarran 
123bb8023b5Sdarran 			count = (uintptr_t) d->last - (uintptr_t) d->first;
124bb8023b5Sdarran 
125bb8023b5Sdarran 			for (p = d->first; p < d->last; p++)
126bb8023b5Sdarran 				*p1++ = *p;
127bb8023b5Sdarran 
128bb8023b5Sdarran 			count += (uintptr_t) d->next - (uintptr_t) d->bufr;
129bb8023b5Sdarran 
130bb8023b5Sdarran 			for (p = d->bufr; p < d->next; p++)
131bb8023b5Sdarran 				*p1++ = *p;
132bb8023b5Sdarran 		}
133bb8023b5Sdarran 
134bb8023b5Sdarran 		d->first = d->bufr;
135bb8023b5Sdarran 		d->next = d->bufr;
136bb8023b5Sdarran 
137*ba2539a9Schs 		dtrace_debug_unlock(i);
138bb8023b5Sdarran 
139bb8023b5Sdarran 		if (count > 0) {
140bb8023b5Sdarran 			char *last = dtrace_debug_bufr + count;
141bb8023b5Sdarran 
142bb8023b5Sdarran 			p = dtrace_debug_bufr;
143bb8023b5Sdarran 
144bb8023b5Sdarran 			while (p < last) {
145bb8023b5Sdarran 				if (*p == '\0') {
146bb8023b5Sdarran 					p++;
147bb8023b5Sdarran 					continue;
148bb8023b5Sdarran 				}
149bb8023b5Sdarran 
150bb8023b5Sdarran 				printf("%s", p);
151bb8023b5Sdarran 
152bb8023b5Sdarran 				p += strlen(p);
153bb8023b5Sdarran 			}
154bb8023b5Sdarran 		}
155bb8023b5Sdarran 	}
156bb8023b5Sdarran }
157bb8023b5Sdarran 
158bb8023b5Sdarran /*
159bb8023b5Sdarran  * Functions below here are called from the probe context, so they can't call
160bb8023b5Sdarran  * _any_ functions outside the dtrace module without running foul of the function
161bb8023b5Sdarran  * boundary trace provider (fbt). The purpose of these functions is limited to
162bb8023b5Sdarran  * buffering debug strings for output when the probe completes on the current CPU.
163bb8023b5Sdarran  */
164bb8023b5Sdarran 
165bb8023b5Sdarran static __inline void
dtrace_debug__putc(int cpu,char c)166*ba2539a9Schs dtrace_debug__putc(int cpu, char c)
167bb8023b5Sdarran {
168*ba2539a9Schs 	struct dtrace_debug_data *d;
169bb8023b5Sdarran 
170*ba2539a9Schs 	d = &dtrace_debug_data[cpu];
171bb8023b5Sdarran 	*d->next++ = c;
172bb8023b5Sdarran 
173bb8023b5Sdarran 	if (d->next == d->last)
174bb8023b5Sdarran 		d->next = d->bufr;
175bb8023b5Sdarran 
176bb8023b5Sdarran 	*(d->next) = '\0';
177bb8023b5Sdarran 
178bb8023b5Sdarran 	if (d->next == d->first)
179bb8023b5Sdarran 		d->first++;
180bb8023b5Sdarran 
181bb8023b5Sdarran 	if (d->first == d->last)
182bb8023b5Sdarran 		d->first = d->bufr;
183bb8023b5Sdarran }
184bb8023b5Sdarran 
185bb8023b5Sdarran static void __used
dtrace_debug_putc(char c)186bb8023b5Sdarran dtrace_debug_putc(char c)
187bb8023b5Sdarran {
188*ba2539a9Schs 	int cpu;
189bb8023b5Sdarran 
190*ba2539a9Schs 	cpu = cpu_number();
191*ba2539a9Schs 	dtrace_debug_lock(cpu);
192bb8023b5Sdarran 
193*ba2539a9Schs 	dtrace_debug__putc(cpu, c);
194*ba2539a9Schs 
195*ba2539a9Schs 	dtrace_debug_unlock(cpu);
196bb8023b5Sdarran }
197bb8023b5Sdarran 
198bb8023b5Sdarran static void __used
dtrace_debug_puts(const char * s)199bb8023b5Sdarran dtrace_debug_puts(const char *s)
200bb8023b5Sdarran {
201*ba2539a9Schs 	int cpu;
202*ba2539a9Schs 
203*ba2539a9Schs 	cpu = cpu_number();
204*ba2539a9Schs 	dtrace_debug_lock(cpu);
205bb8023b5Sdarran 
206bb8023b5Sdarran 	while (*s != '\0')
207*ba2539a9Schs 		dtrace_debug__putc(cpu, *s++);
208bb8023b5Sdarran 
209*ba2539a9Schs 	dtrace_debug__putc(cpu, '\0');
210bb8023b5Sdarran 
211*ba2539a9Schs 	dtrace_debug_unlock(cpu);
212bb8023b5Sdarran }
213bb8023b5Sdarran 
214bb8023b5Sdarran /*
215bb8023b5Sdarran  * Snaffled from sys/kern/subr_prf.c
216bb8023b5Sdarran  *
217bb8023b5Sdarran  * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
218bb8023b5Sdarran  * order; return an optional length and a pointer to the last character
219bb8023b5Sdarran  * written in the buffer (i.e., the first character of the string).
220*ba2539a9Schs  * The buffer pointed to by `nbuf' must have length >= MAXNBUF.
221bb8023b5Sdarran  */
222bb8023b5Sdarran static char *
dtrace_debug_ksprintn(char * nbuf,uintmax_t num,int base,int * lenp,int upper)223*ba2539a9Schs dtrace_debug_ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
224bb8023b5Sdarran {
225bb8023b5Sdarran 	char *p, c;
226bb8023b5Sdarran 
227*ba2539a9Schs 	p = nbuf;
228bb8023b5Sdarran 	*p = '\0';
229bb8023b5Sdarran 	do {
230bb8023b5Sdarran 		c = hex2ascii(num % base);
231bb8023b5Sdarran 		*++p = upper ? toupper(c) : c;
232bb8023b5Sdarran 	} while (num /= base);
233bb8023b5Sdarran 	if (lenp)
234*ba2539a9Schs 		*lenp = p - nbuf;
235bb8023b5Sdarran 	return (p);
236bb8023b5Sdarran }
237bb8023b5Sdarran 
238bb8023b5Sdarran #define MAXNBUF (sizeof(intmax_t) * NBBY + 1)
239bb8023b5Sdarran 
240bb8023b5Sdarran static void
dtrace_debug_vprintf(int cpu,const char * fmt,va_list ap)241*ba2539a9Schs dtrace_debug_vprintf(int cpu, const char *fmt, va_list ap)
242bb8023b5Sdarran {
243*ba2539a9Schs 	char nbuf[MAXNBUF];
244bb8023b5Sdarran 	const char *p, *percent, *q;
245bb8023b5Sdarran 	u_char *up;
246bb8023b5Sdarran 	int ch, n;
247bb8023b5Sdarran 	uintmax_t num;
248bb8023b5Sdarran 	int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
249bb8023b5Sdarran 	int cflag, hflag, jflag, tflag, zflag;
250bb8023b5Sdarran 	int dwidth, upper;
251bb8023b5Sdarran 	int radix = 10;
252bb8023b5Sdarran 	char padc;
253bb8023b5Sdarran 	int stop = 0, retval = 0;
254bb8023b5Sdarran 
255bb8023b5Sdarran 	num = 0;
256bb8023b5Sdarran 
257bb8023b5Sdarran 	if (fmt == NULL)
258bb8023b5Sdarran 		fmt = "(fmt null)\n";
259bb8023b5Sdarran 
260bb8023b5Sdarran 	for (;;) {
261bb8023b5Sdarran 		padc = ' ';
262bb8023b5Sdarran 		width = 0;
263bb8023b5Sdarran 		while ((ch = (u_char)*fmt++) != '%' || stop) {
264bb8023b5Sdarran 			if (ch == '\0') {
265*ba2539a9Schs 				dtrace_debug__putc(cpu, '\0');
266bb8023b5Sdarran 				return;
267bb8023b5Sdarran 			}
268*ba2539a9Schs 			dtrace_debug__putc(cpu, ch);
269bb8023b5Sdarran 		}
270bb8023b5Sdarran 		percent = fmt - 1;
271bb8023b5Sdarran 		qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
272bb8023b5Sdarran 		sign = 0; dot = 0; dwidth = 0; upper = 0;
273bb8023b5Sdarran 		cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0;
274bb8023b5Sdarran reswitch:	switch (ch = (u_char)*fmt++) {
275bb8023b5Sdarran 		case '.':
276bb8023b5Sdarran 			dot = 1;
277bb8023b5Sdarran 			goto reswitch;
278bb8023b5Sdarran 		case '#':
279bb8023b5Sdarran 			sharpflag = 1;
280bb8023b5Sdarran 			goto reswitch;
281bb8023b5Sdarran 		case '+':
282bb8023b5Sdarran 			sign = 1;
283bb8023b5Sdarran 			goto reswitch;
284bb8023b5Sdarran 		case '-':
285bb8023b5Sdarran 			ladjust = 1;
286bb8023b5Sdarran 			goto reswitch;
287bb8023b5Sdarran 		case '%':
288*ba2539a9Schs 			dtrace_debug__putc(cpu, ch);
289bb8023b5Sdarran 			break;
290bb8023b5Sdarran 		case '*':
291bb8023b5Sdarran 			if (!dot) {
292bb8023b5Sdarran 				width = va_arg(ap, int);
293bb8023b5Sdarran 				if (width < 0) {
294bb8023b5Sdarran 					ladjust = !ladjust;
295bb8023b5Sdarran 					width = -width;
296bb8023b5Sdarran 				}
297bb8023b5Sdarran 			} else {
298bb8023b5Sdarran 				dwidth = va_arg(ap, int);
299bb8023b5Sdarran 			}
300bb8023b5Sdarran 			goto reswitch;
301bb8023b5Sdarran 		case '0':
302bb8023b5Sdarran 			if (!dot) {
303bb8023b5Sdarran 				padc = '0';
304bb8023b5Sdarran 				goto reswitch;
305bb8023b5Sdarran 			}
306bb8023b5Sdarran 		case '1': case '2': case '3': case '4':
307bb8023b5Sdarran 		case '5': case '6': case '7': case '8': case '9':
308bb8023b5Sdarran 				for (n = 0;; ++fmt) {
309bb8023b5Sdarran 					n = n * 10 + ch - '0';
310bb8023b5Sdarran 					ch = *fmt;
311bb8023b5Sdarran 					if (ch < '0' || ch > '9')
312bb8023b5Sdarran 						break;
313bb8023b5Sdarran 				}
314bb8023b5Sdarran 			if (dot)
315bb8023b5Sdarran 				dwidth = n;
316bb8023b5Sdarran 			else
317bb8023b5Sdarran 				width = n;
318bb8023b5Sdarran 			goto reswitch;
319bb8023b5Sdarran 		case 'b':
320bb8023b5Sdarran 			num = (u_int)va_arg(ap, int);
321bb8023b5Sdarran 			p = va_arg(ap, char *);
322*ba2539a9Schs 			for (q = dtrace_debug_ksprintn(nbuf, num, *p++, NULL, 0); *q;)
323*ba2539a9Schs 				dtrace_debug__putc(cpu, *q--);
324bb8023b5Sdarran 
325bb8023b5Sdarran 			if (num == 0)
326bb8023b5Sdarran 				break;
327bb8023b5Sdarran 
328bb8023b5Sdarran 			for (tmp = 0; *p;) {
329bb8023b5Sdarran 				n = *p++;
330bb8023b5Sdarran 				if (num & (1 << (n - 1))) {
331*ba2539a9Schs 					dtrace_debug__putc(cpu, tmp ? ',' : '<');
332bb8023b5Sdarran 					for (; (n = *p) > ' '; ++p)
333*ba2539a9Schs 						dtrace_debug__putc(cpu, n);
334bb8023b5Sdarran 					tmp = 1;
335bb8023b5Sdarran 				} else
336bb8023b5Sdarran 					for (; *p > ' '; ++p)
337bb8023b5Sdarran 						continue;
338bb8023b5Sdarran 			}
339bb8023b5Sdarran 			if (tmp)
340*ba2539a9Schs 				dtrace_debug__putc(cpu, '>');
341bb8023b5Sdarran 			break;
342bb8023b5Sdarran 		case 'c':
343*ba2539a9Schs 			dtrace_debug__putc(cpu, va_arg(ap, int));
344bb8023b5Sdarran 			break;
345bb8023b5Sdarran 		case 'D':
346bb8023b5Sdarran 			up = va_arg(ap, u_char *);
347bb8023b5Sdarran 			p = va_arg(ap, char *);
348bb8023b5Sdarran 			if (!width)
349bb8023b5Sdarran 				width = 16;
350bb8023b5Sdarran 			while(width--) {
351*ba2539a9Schs 				dtrace_debug__putc(cpu, hex2ascii(*up >> 4));
352*ba2539a9Schs 				dtrace_debug__putc(cpu, hex2ascii(*up & 0x0f));
353bb8023b5Sdarran 				up++;
354bb8023b5Sdarran 				if (width)
355bb8023b5Sdarran 					for (q=p;*q;q++)
356*ba2539a9Schs 						dtrace_debug__putc(cpu, *q);
357bb8023b5Sdarran 			}
358bb8023b5Sdarran 			break;
359bb8023b5Sdarran 		case 'd':
360bb8023b5Sdarran 		case 'i':
361bb8023b5Sdarran 			base = 10;
362bb8023b5Sdarran 			sign = 1;
363bb8023b5Sdarran 			goto handle_sign;
364bb8023b5Sdarran 		case 'h':
365bb8023b5Sdarran 			if (hflag) {
366bb8023b5Sdarran 				hflag = 0;
367bb8023b5Sdarran 				cflag = 1;
368bb8023b5Sdarran 			} else
369bb8023b5Sdarran 				hflag = 1;
370bb8023b5Sdarran 			goto reswitch;
371bb8023b5Sdarran 		case 'j':
372bb8023b5Sdarran 			jflag = 1;
373bb8023b5Sdarran 			goto reswitch;
374bb8023b5Sdarran 		case 'l':
375bb8023b5Sdarran 			if (lflag) {
376bb8023b5Sdarran 				lflag = 0;
377bb8023b5Sdarran 				qflag = 1;
378bb8023b5Sdarran 			} else
379bb8023b5Sdarran 				lflag = 1;
380bb8023b5Sdarran 			goto reswitch;
381bb8023b5Sdarran 		case 'n':
382bb8023b5Sdarran 			if (jflag)
383bb8023b5Sdarran 				*(va_arg(ap, intmax_t *)) = retval;
384bb8023b5Sdarran 			else if (qflag)
385bb8023b5Sdarran 				*(va_arg(ap, quad_t *)) = retval;
386bb8023b5Sdarran 			else if (lflag)
387bb8023b5Sdarran 				*(va_arg(ap, long *)) = retval;
388bb8023b5Sdarran 			else if (zflag)
389bb8023b5Sdarran 				*(va_arg(ap, size_t *)) = retval;
390bb8023b5Sdarran 			else if (hflag)
391bb8023b5Sdarran 				*(va_arg(ap, short *)) = retval;
392bb8023b5Sdarran 			else if (cflag)
393bb8023b5Sdarran 				*(va_arg(ap, char *)) = retval;
394bb8023b5Sdarran 			else
395bb8023b5Sdarran 				*(va_arg(ap, int *)) = retval;
396bb8023b5Sdarran 			break;
397bb8023b5Sdarran 		case 'o':
398bb8023b5Sdarran 			base = 8;
399bb8023b5Sdarran 			goto handle_nosign;
400bb8023b5Sdarran 		case 'p':
401bb8023b5Sdarran 			base = 16;
402bb8023b5Sdarran 			sharpflag = (width == 0);
403bb8023b5Sdarran 			sign = 0;
404bb8023b5Sdarran 			num = (uintptr_t)va_arg(ap, void *);
405bb8023b5Sdarran 			goto number;
406bb8023b5Sdarran 		case 'q':
407bb8023b5Sdarran 			qflag = 1;
408bb8023b5Sdarran 			goto reswitch;
409bb8023b5Sdarran 		case 'r':
410bb8023b5Sdarran 			base = radix;
411bb8023b5Sdarran 			if (sign)
412bb8023b5Sdarran 				goto handle_sign;
413bb8023b5Sdarran 			goto handle_nosign;
414bb8023b5Sdarran 		case 's':
415bb8023b5Sdarran 			p = va_arg(ap, char *);
416bb8023b5Sdarran 			if (p == NULL)
417bb8023b5Sdarran 				p = "(null)";
418bb8023b5Sdarran 			if (!dot)
419bb8023b5Sdarran 				n = strlen (p);
420bb8023b5Sdarran 			else
421bb8023b5Sdarran 				for (n = 0; n < dwidth && p[n]; n++)
422bb8023b5Sdarran 					continue;
423bb8023b5Sdarran 
424bb8023b5Sdarran 			width -= n;
425bb8023b5Sdarran 
426bb8023b5Sdarran 			if (!ladjust && width > 0)
427bb8023b5Sdarran 				while (width--)
428*ba2539a9Schs 					dtrace_debug__putc(cpu, padc);
429bb8023b5Sdarran 			while (n--)
430*ba2539a9Schs 				dtrace_debug__putc(cpu, *p++);
431bb8023b5Sdarran 			if (ladjust && width > 0)
432bb8023b5Sdarran 				while (width--)
433*ba2539a9Schs 					dtrace_debug__putc(cpu, padc);
434bb8023b5Sdarran 			break;
435bb8023b5Sdarran 		case 't':
436bb8023b5Sdarran 			tflag = 1;
437bb8023b5Sdarran 			goto reswitch;
438bb8023b5Sdarran 		case 'u':
439bb8023b5Sdarran 			base = 10;
440bb8023b5Sdarran 			goto handle_nosign;
441bb8023b5Sdarran 		case 'X':
442bb8023b5Sdarran 			upper = 1;
443bb8023b5Sdarran 		case 'x':
444bb8023b5Sdarran 			base = 16;
445bb8023b5Sdarran 			goto handle_nosign;
446bb8023b5Sdarran 		case 'y':
447bb8023b5Sdarran 			base = 16;
448bb8023b5Sdarran 			sign = 1;
449bb8023b5Sdarran 			goto handle_sign;
450bb8023b5Sdarran 		case 'z':
451bb8023b5Sdarran 			zflag = 1;
452bb8023b5Sdarran 			goto reswitch;
453bb8023b5Sdarran handle_nosign:
454bb8023b5Sdarran 			sign = 0;
455bb8023b5Sdarran 			if (jflag)
456bb8023b5Sdarran 				num = va_arg(ap, uintmax_t);
457bb8023b5Sdarran 			else if (qflag)
458bb8023b5Sdarran 				num = va_arg(ap, u_quad_t);
459bb8023b5Sdarran 			else if (tflag)
460bb8023b5Sdarran 				num = va_arg(ap, ptrdiff_t);
461bb8023b5Sdarran 			else if (lflag)
462bb8023b5Sdarran 				num = va_arg(ap, u_long);
463bb8023b5Sdarran 			else if (zflag)
464bb8023b5Sdarran 				num = va_arg(ap, size_t);
465bb8023b5Sdarran 			else if (hflag)
466bb8023b5Sdarran 				num = (u_short)va_arg(ap, int);
467bb8023b5Sdarran 			else if (cflag)
468bb8023b5Sdarran 				num = (u_char)va_arg(ap, int);
469bb8023b5Sdarran 			else
470bb8023b5Sdarran 				num = va_arg(ap, u_int);
471bb8023b5Sdarran 			goto number;
472bb8023b5Sdarran handle_sign:
473bb8023b5Sdarran 			if (jflag)
474bb8023b5Sdarran 				num = va_arg(ap, intmax_t);
475bb8023b5Sdarran 			else if (qflag)
476bb8023b5Sdarran 				num = va_arg(ap, quad_t);
477bb8023b5Sdarran 			else if (tflag)
478bb8023b5Sdarran 				num = va_arg(ap, ptrdiff_t);
479bb8023b5Sdarran 			else if (lflag)
480bb8023b5Sdarran 				num = va_arg(ap, long);
481bb8023b5Sdarran 			else if (zflag)
482bb8023b5Sdarran 				num = va_arg(ap, size_t);
483bb8023b5Sdarran 			else if (hflag)
484bb8023b5Sdarran 				num = (short)va_arg(ap, int);
485bb8023b5Sdarran 			else if (cflag)
486bb8023b5Sdarran 				num = (char)va_arg(ap, int);
487bb8023b5Sdarran 			else
488bb8023b5Sdarran 				num = va_arg(ap, int);
489bb8023b5Sdarran number:
490bb8023b5Sdarran 			if (sign && (intmax_t)num < 0) {
491bb8023b5Sdarran 				neg = 1;
492bb8023b5Sdarran 				num = -(intmax_t)num;
493bb8023b5Sdarran 			}
494*ba2539a9Schs 			p = dtrace_debug_ksprintn(nbuf, num, base, &tmp, upper);
495bb8023b5Sdarran 			if (sharpflag && num != 0) {
496bb8023b5Sdarran 				if (base == 8)
497bb8023b5Sdarran 					tmp++;
498bb8023b5Sdarran 				else if (base == 16)
499bb8023b5Sdarran 					tmp += 2;
500bb8023b5Sdarran 			}
501bb8023b5Sdarran 			if (neg)
502bb8023b5Sdarran 				tmp++;
503bb8023b5Sdarran 
504bb8023b5Sdarran 			if (!ladjust && padc != '0' && width
505bb8023b5Sdarran 			    && (width -= tmp) > 0)
506bb8023b5Sdarran 				while (width--)
507*ba2539a9Schs 					dtrace_debug__putc(cpu, padc);
508bb8023b5Sdarran 			if (neg)
509*ba2539a9Schs 				dtrace_debug__putc(cpu, '-');
510bb8023b5Sdarran 			if (sharpflag && num != 0) {
511bb8023b5Sdarran 				if (base == 8) {
512*ba2539a9Schs 					dtrace_debug__putc(cpu, '0');
513bb8023b5Sdarran 				} else if (base == 16) {
514*ba2539a9Schs 					dtrace_debug__putc(cpu, '0');
515*ba2539a9Schs 					dtrace_debug__putc(cpu, 'x');
516bb8023b5Sdarran 				}
517bb8023b5Sdarran 			}
518bb8023b5Sdarran 			if (!ladjust && width && (width -= tmp) > 0)
519bb8023b5Sdarran 				while (width--)
520*ba2539a9Schs 					dtrace_debug__putc(cpu, padc);
521bb8023b5Sdarran 
522bb8023b5Sdarran 			while (*p)
523*ba2539a9Schs 				dtrace_debug__putc(cpu, *p--);
524bb8023b5Sdarran 
525bb8023b5Sdarran 			if (ladjust && width && (width -= tmp) > 0)
526bb8023b5Sdarran 				while (width--)
527*ba2539a9Schs 					dtrace_debug__putc(cpu, padc);
528bb8023b5Sdarran 
529bb8023b5Sdarran 			break;
530bb8023b5Sdarran 		default:
531bb8023b5Sdarran 			while (percent < fmt)
532*ba2539a9Schs 				dtrace_debug__putc(cpu, *percent++);
533bb8023b5Sdarran 			/*
534bb8023b5Sdarran 			 * Since we ignore an formatting argument it is no
535bb8023b5Sdarran 			 * longer safe to obey the remaining formatting
536bb8023b5Sdarran 			 * arguments as the arguments will no longer match
537bb8023b5Sdarran 			 * the format specs.
538bb8023b5Sdarran 			 */
539bb8023b5Sdarran 			stop = 1;
540bb8023b5Sdarran 			break;
541bb8023b5Sdarran 		}
542bb8023b5Sdarran 	}
543bb8023b5Sdarran 
544*ba2539a9Schs 	dtrace_debug__putc(cpu, '\0');
545bb8023b5Sdarran }
546bb8023b5Sdarran 
547bb8023b5Sdarran void
dtrace_debug_printf(const char * fmt,...)548bb8023b5Sdarran dtrace_debug_printf(const char *fmt, ...)
549bb8023b5Sdarran {
550bb8023b5Sdarran 	va_list ap;
551*ba2539a9Schs 	int cpu;
552bb8023b5Sdarran 
553*ba2539a9Schs 	cpu = cpu_number();
554*ba2539a9Schs 	dtrace_debug_lock(cpu);
555bb8023b5Sdarran 
556bb8023b5Sdarran 	va_start(ap, fmt);
557bb8023b5Sdarran 
558*ba2539a9Schs 	dtrace_debug_vprintf(cpu, fmt, ap);
559bb8023b5Sdarran 
560bb8023b5Sdarran 	va_end(ap);
561bb8023b5Sdarran 
562*ba2539a9Schs 	dtrace_debug_unlock(cpu);
563bb8023b5Sdarran }
564bb8023b5Sdarran 
565bb8023b5Sdarran #else
566bb8023b5Sdarran 
567bb8023b5Sdarran #define dtrace_debug_output()
568bb8023b5Sdarran #define dtrace_debug_puts(_s)
569bb8023b5Sdarran #define dtrace_debug_printf(fmt, ...)
570bb8023b5Sdarran 
571*ba2539a9Schs static void
dtrace_debug_init(void * dummy)572*ba2539a9Schs dtrace_debug_init(void *dummy)
573*ba2539a9Schs {
574*ba2539a9Schs }
575*ba2539a9Schs 
576bb8023b5Sdarran #endif
577