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