kdump.c revision 165916
10SN/A/*-
27549SN/A * Copyright (c) 1988, 1993
30SN/A *	The Regents of the University of California.  All rights reserved.
40SN/A *
50SN/A * Redistribution and use in source and binary forms, with or without
60SN/A * modification, are permitted provided that the following conditions
72362SN/A * are met:
80SN/A * 1. Redistributions of source code must retain the above copyright
92362SN/A *    notice, this list of conditions and the following disclaimer.
100SN/A * 2. Redistributions in binary form must reproduce the above copyright
110SN/A *    notice, this list of conditions and the following disclaimer in the
120SN/A *    documentation and/or other materials provided with the distribution.
130SN/A * 3. All advertising materials mentioning features or use of this software
140SN/A *    must display the following acknowledgement:
150SN/A *	This product includes software developed by the University of
160SN/A *	California, Berkeley and its contributors.
170SN/A * 4. Neither the name of the University nor the names of its contributors
180SN/A *    may be used to endorse or promote products derived from this software
190SN/A *    without specific prior written permission.
200SN/A *
212362SN/A * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
222362SN/A * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
232362SN/A * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
240SN/A * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
250SN/A * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
260SN/A * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
270SN/A * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
280SN/A * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
290SN/A * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
300SN/A * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
310SN/A * SUCH DAMAGE.
327549SN/A */
330SN/A
347549SN/A#ifndef lint
350SN/Astatic const char copyright[] =
360SN/A"@(#) Copyright (c) 1988, 1993\n\
370SN/A	The Regents of the University of California.  All rights reserved.\n";
380SN/A#endif /* not lint */
390SN/A
400SN/A#ifndef lint
410SN/A#if 0
420SN/Astatic char sccsid[] = "@(#)kdump.c	8.1 (Berkeley) 6/6/93";
430SN/A#endif
440SN/A#endif /* not lint */
450SN/A#include <sys/cdefs.h>
460SN/A__FBSDID("$FreeBSD: head/usr.bin/kdump/kdump.c 165916 2007-01-09 17:50:05Z jhb $");
470SN/A
480SN/A#define _KERNEL
490SN/Aextern int errno;
500SN/A#include <sys/errno.h>
510SN/A#undef _KERNEL
520SN/A#include <sys/param.h>
530SN/A#include <sys/errno.h>
540SN/A#define _KERNEL
550SN/A#include <sys/time.h>
567549SN/A#undef _KERNEL
570SN/A#include <sys/uio.h>
580SN/A#include <sys/ktrace.h>
590SN/A#include <sys/ioctl.h>
600SN/A#include <sys/ptrace.h>
610SN/A#include <sys/socket.h>
620SN/A#include <dlfcn.h>
630SN/A#include <err.h>
647549SN/A#include <locale.h>
657549SN/A#include <stdio.h>
660SN/A#include <stdlib.h>
670SN/A#include <string.h>
680SN/A#include <unistd.h>
690SN/A#include <vis.h>
700SN/A#include "ktrace.h"
710SN/A#include "kdump_subr.h"
720SN/A
730SN/Aint fread_tail(void *, int, int);
740SN/Avoid dumpheader(struct ktr_header *);
757549SN/Avoid ktrsyscall(struct ktr_syscall *);
760SN/Avoid ktrsysret(struct ktr_sysret *);
777549SN/Avoid ktrnamei(char *, int);
780SN/Avoid hexdump(char *, int, int);
797549SN/Avoid visdump(char *, int, int);
807549SN/Avoid ktrgenio(struct ktr_genio *, int);
810SN/Avoid ktrpsig(struct ktr_psig *);
820SN/Avoid ktrcsw(struct ktr_csw *);
830SN/Avoid ktruser(int, unsigned char *);
847549SN/Avoid usage(void);
850SN/Aconst char *ioctlname(u_long);
860SN/A
870SN/Aint timestamp, decimal, fancy = 1, suppressdata, tail, threads, maxdata;
880SN/Aconst char *tracefile = DEF_TRACEFILE;
890SN/Astruct ktr_header ktr_header;
900SN/A
910SN/A#define eqs(s1, s2)	(strcmp((s1), (s2)) == 0)
927549SN/A
930SN/Aint
940SN/Amain(int argc, char *argv[])
950SN/A{
960SN/A	int ch, ktrlen, size;
977549SN/A	void *m;
980SN/A	int trpoints = ALL_POINTS;
990SN/A	int drop_logged;
1000SN/A	pid_t pid = 0;
1010SN/A
1020SN/A	(void) setlocale(LC_CTYPE, "");
1030SN/A
1040SN/A	while ((ch = getopt(argc,argv,"f:dElm:np:HRsTt:")) != -1)
105		switch((char)ch) {
106		case 'f':
107			tracefile = optarg;
108			break;
109		case 'd':
110			decimal = 1;
111			break;
112		case 'l':
113			tail = 1;
114			break;
115		case 'm':
116			maxdata = atoi(optarg);
117			break;
118		case 'n':
119			fancy = 0;
120			break;
121		case 'p':
122			pid = atoi(optarg);
123			break;
124		case 's':
125			suppressdata = 1;
126			break;
127		case 'E':
128			timestamp = 3;	/* elapsed timestamp */
129			break;
130		case 'H':
131			threads = 1;
132			break;
133		case 'R':
134			timestamp = 2;	/* relative timestamp */
135			break;
136		case 'T':
137			timestamp = 1;
138			break;
139		case 't':
140			trpoints = getpoints(optarg);
141			if (trpoints < 0)
142				errx(1, "unknown trace point in %s", optarg);
143			break;
144		default:
145			usage();
146		}
147
148	if (argc > optind)
149		usage();
150
151	m = (void *)malloc(size = 1025);
152	if (m == NULL)
153		errx(1, "%s", strerror(ENOMEM));
154	if (!freopen(tracefile, "r", stdin))
155		err(1, "%s", tracefile);
156	drop_logged = 0;
157	while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) {
158		if (ktr_header.ktr_type & KTR_DROP) {
159			ktr_header.ktr_type &= ~KTR_DROP;
160			if (!drop_logged && threads) {
161				(void)printf("%6d %6d %-8.*s Events dropped.\n",
162				    ktr_header.ktr_pid, ktr_header.ktr_tid >
163				    0 ? ktr_header.ktr_tid : 0, MAXCOMLEN,
164				    ktr_header.ktr_comm);
165				drop_logged = 1;
166			} else if (!drop_logged) {
167				(void)printf("%6d %-8.*s Events dropped.\n",
168				    ktr_header.ktr_pid, MAXCOMLEN,
169				    ktr_header.ktr_comm);
170				drop_logged = 1;
171			}
172		}
173		if (trpoints & (1<<ktr_header.ktr_type))
174			if (pid == 0 || ktr_header.ktr_pid == pid)
175				dumpheader(&ktr_header);
176		if ((ktrlen = ktr_header.ktr_len) < 0)
177			errx(1, "bogus length 0x%x", ktrlen);
178		if (ktrlen > size) {
179			m = (void *)realloc(m, ktrlen+1);
180			if (m == NULL)
181				errx(1, "%s", strerror(ENOMEM));
182			size = ktrlen;
183		}
184		if (ktrlen && fread_tail(m, ktrlen, 1) == 0)
185			errx(1, "data too short");
186		if (pid && ktr_header.ktr_pid != pid)
187			continue;
188		if ((trpoints & (1<<ktr_header.ktr_type)) == 0)
189			continue;
190		drop_logged = 0;
191		switch (ktr_header.ktr_type) {
192		case KTR_SYSCALL:
193			ktrsyscall((struct ktr_syscall *)m);
194			break;
195		case KTR_SYSRET:
196			ktrsysret((struct ktr_sysret *)m);
197			break;
198		case KTR_NAMEI:
199			ktrnamei(m, ktrlen);
200			break;
201		case KTR_GENIO:
202			ktrgenio((struct ktr_genio *)m, ktrlen);
203			break;
204		case KTR_PSIG:
205			ktrpsig((struct ktr_psig *)m);
206			break;
207		case KTR_CSW:
208			ktrcsw((struct ktr_csw *)m);
209			break;
210		case KTR_USER:
211			ktruser(ktrlen, m);
212			break;
213		default:
214			printf("\n");
215			break;
216		}
217		if (tail)
218			(void)fflush(stdout);
219	}
220	return 0;
221}
222
223int
224fread_tail(void *buf, int size, int num)
225{
226	int i;
227
228	while ((i = fread(buf, size, num, stdin)) == 0 && tail) {
229		(void)sleep(1);
230		clearerr(stdin);
231	}
232	return (i);
233}
234
235void
236dumpheader(struct ktr_header *kth)
237{
238	static char unknown[64];
239	static struct timeval prevtime, temp;
240	const char *type;
241
242	switch (kth->ktr_type) {
243	case KTR_SYSCALL:
244		type = "CALL";
245		break;
246	case KTR_SYSRET:
247		type = "RET ";
248		break;
249	case KTR_NAMEI:
250		type = "NAMI";
251		break;
252	case KTR_GENIO:
253		type = "GIO ";
254		break;
255	case KTR_PSIG:
256		type = "PSIG";
257		break;
258	case KTR_CSW:
259		type = "CSW";
260		break;
261	case KTR_USER:
262		type = "USER";
263		break;
264	default:
265		(void)sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type);
266		type = unknown;
267	}
268
269	/*
270	 * The ktr_tid field was previously the ktr_buffer field, which held
271	 * the kernel pointer value for the buffer associated with data
272	 * following the record header.  It now holds a threadid, but only
273	 * for trace files after the change.  Older trace files still contain
274	 * kernel pointers.  Detect this and suppress the results by printing
275	 * negative tid's as 0.
276	 */
277	if (threads)
278		(void)printf("%6d %6d %-8.*s ", kth->ktr_pid, kth->ktr_tid >
279		    0 ? kth->ktr_tid : 0, MAXCOMLEN, kth->ktr_comm);
280	else
281		(void)printf("%6d %-8.*s ", kth->ktr_pid, MAXCOMLEN,
282		    kth->ktr_comm);
283	if (timestamp) {
284		if (timestamp == 3) {
285			if (prevtime.tv_sec == 0)
286				prevtime = kth->ktr_time;
287			timevalsub(&kth->ktr_time, &prevtime);
288		}
289		if (timestamp == 2) {
290			temp = kth->ktr_time;
291			timevalsub(&kth->ktr_time, &prevtime);
292			prevtime = temp;
293		}
294		(void)printf("%ld.%06ld ",
295		    kth->ktr_time.tv_sec, kth->ktr_time.tv_usec);
296	}
297	(void)printf("%s  ", type);
298}
299
300#include <sys/syscall.h>
301#define KTRACE
302#include <sys/kern/syscalls.c>
303#undef KTRACE
304int nsyscalls = sizeof (syscallnames) / sizeof (syscallnames[0]);
305
306static const char *ptrace_ops[] = {
307	"PT_TRACE_ME",	"PT_READ_I",	"PT_READ_D",	"PT_READ_U",
308	"PT_WRITE_I",	"PT_WRITE_D",	"PT_WRITE_U",	"PT_CONTINUE",
309	"PT_KILL",	"PT_STEP",	"PT_ATTACH",	"PT_DETACH",
310};
311
312void
313ktrsyscall(struct ktr_syscall *ktr)
314{
315	int narg = ktr->ktr_narg;
316	register_t *ip;
317
318	if (ktr->ktr_code >= nsyscalls || ktr->ktr_code < 0)
319		(void)printf("[%d]", ktr->ktr_code);
320	else
321		(void)printf("%s", syscallnames[ktr->ktr_code]);
322	ip = &ktr->ktr_args[0];
323	if (narg) {
324		char c = '(';
325		if (fancy) {
326
327#define print_number(i,n,c) do {                      \
328	if (decimal)                                  \
329		(void)printf("%c%ld", c, (long)*i);   \
330	else                                          \
331		(void)printf("%c%#lx", c, (long)*i);  \
332	i++;                                          \
333	n--;                                          \
334	c = ',';                                      \
335	} while (0);
336
337			if (ktr->ktr_code == SYS_ioctl) {
338				const char *cp;
339				print_number(ip,narg,c);
340				if ((cp = ioctlname(*ip)) != NULL)
341					(void)printf(",%s", cp);
342				else {
343					if (decimal)
344						(void)printf(",%ld", (long)*ip);
345					else
346						(void)printf(",%#lx ", (long)*ip);
347				}
348				c = ',';
349				ip++;
350				narg--;
351			} else if (ktr->ktr_code == SYS_ptrace) {
352				if ((size_t)*ip < sizeof(ptrace_ops) /
353				    sizeof(ptrace_ops[0]) && *ip >= 0)
354					(void)printf("(%s", ptrace_ops[*ip]);
355#ifdef PT_GETREGS
356				else if (*ip == PT_GETREGS)
357					(void)printf("(%s", "PT_GETREGS");
358#endif
359#ifdef PT_SETREGS
360				else if (*ip == PT_SETREGS)
361					(void)printf("(%s", "PT_SETREGS");
362#endif
363#ifdef PT_GETFPREGS
364				else if (*ip == PT_GETFPREGS)
365					(void)printf("(%s", "PT_GETFPREGS");
366#endif
367#ifdef PT_SETFPREGS
368				else if (*ip == PT_SETFPREGS)
369					(void)printf("(%s", "PT_SETFPREGS");
370#endif
371#ifdef PT_GETDBREGS
372				else if (*ip == PT_GETDBREGS)
373					(void)printf("(%s", "PT_GETDBREGS");
374#endif
375#ifdef PT_SETDBREGS
376				else if (*ip == PT_SETDBREGS)
377					(void)printf("(%s", "PT_SETDBREGS");
378#endif
379				else
380					(void)printf("(%ld", (long)*ip);
381				c = ',';
382				ip++;
383				narg--;
384			} else if (ktr->ktr_code == SYS_access ||
385				   ktr->ktr_code == SYS_eaccess) {
386				print_number(ip,narg,c);
387				(void)putchar(',');
388				accessmodename ((int)*ip);
389				ip++;
390				narg--;
391			} else if (ktr->ktr_code == SYS_open) {
392				int	flags;
393				int	mode;
394				print_number(ip,narg,c);
395				flags = *ip;
396				mode = *++ip;
397				(void)putchar(',');
398				flagsandmodename (flags, mode, decimal);
399				ip++;
400				narg-=2;
401			} else if (ktr->ktr_code == SYS_wait4) {
402				print_number(ip,narg,c);
403				print_number(ip,narg,c);
404				(void)putchar(',');
405				wait4optname ((int)*ip);
406				ip++;
407				narg--;
408			} else if (ktr->ktr_code == SYS_chmod ||
409				   ktr->ktr_code == SYS_fchmod ||
410				   ktr->ktr_code == SYS_lchmod) {
411				print_number(ip,narg,c);
412				(void)putchar(',');
413				modename ((int)*ip);
414				ip++;
415				narg--;
416			} else if (ktr->ktr_code == SYS_mknod) {
417				print_number(ip,narg,c);
418				(void)putchar(',');
419				modename ((int)*ip);
420				ip++;
421				narg--;
422			} else if (ktr->ktr_code == SYS_getfsstat) {
423				print_number(ip,narg,c);
424				print_number(ip,narg,c);
425				(void)putchar(',');
426				getfsstatflagsname ((int)*ip);
427				ip++;
428				narg--;
429			} else if (ktr->ktr_code == SYS_mount) {
430				print_number(ip,narg,c);
431				print_number(ip,narg,c);
432				(void)putchar(',');
433				mountflagsname ((int)*ip);
434				ip++;
435				narg--;
436			} else if (ktr->ktr_code == SYS_unmount) {
437				print_number(ip,narg,c);
438				(void)putchar(',');
439				mountflagsname ((int)*ip);
440				ip++;
441				narg--;
442			} else if (ktr->ktr_code == SYS_recvmsg ||
443				   ktr->ktr_code == SYS_sendmsg) {
444				print_number(ip,narg,c);
445				print_number(ip,narg,c);
446				(void)putchar(',');
447				sendrecvflagsname ((int)*ip);
448				ip++;
449				narg--;
450			} else if (ktr->ktr_code == SYS_recvfrom ||
451				   ktr->ktr_code == SYS_sendto) {
452				print_number(ip,narg,c);
453				print_number(ip,narg,c);
454				print_number(ip,narg,c);
455				(void)putchar(',');
456				sendrecvflagsname ((int)*ip);
457				ip++;
458				narg--;
459			} else if (ktr->ktr_code == SYS_chflags ||
460				   ktr->ktr_code == SYS_fchflags ||
461				   ktr->ktr_code == SYS_lchflags) {
462				print_number(ip,narg,c);
463				(void)putchar(',');
464				modename((int)*ip);
465				ip++;
466				narg--;
467			} else if (ktr->ktr_code == SYS_kill) {
468				print_number(ip,narg,c);
469				(void)putchar(',');
470				signame((int)*ip);
471				ip++;
472				narg--;
473			} else if (ktr->ktr_code == SYS_reboot) {
474				(void)putchar('(');
475				rebootoptname((int)*ip);
476				ip++;
477				narg--;
478			} else if (ktr->ktr_code == SYS_umask) {
479				(void)putchar('(');
480				modename((int)*ip);
481				ip++;
482				narg--;
483			} else if (ktr->ktr_code == SYS_msync) {
484				print_number(ip,narg,c);
485				print_number(ip,narg,c);
486				(void)putchar(',');
487				msyncflagsname((int)*ip);
488				ip++;
489				narg--;
490			} else if (ktr->ktr_code == SYS_mmap) {
491				print_number(ip,narg,c);
492				print_number(ip,narg,c);
493				(void)putchar(',');
494				mmapprotname ((int)*ip);
495				(void)putchar(',');
496				ip++;
497				narg--;
498				mmapflagsname ((int)*ip);
499				ip++;
500				narg--;
501			} else if (ktr->ktr_code == SYS_mprotect) {
502				print_number(ip,narg,c);
503				print_number(ip,narg,c);
504				(void)putchar(',');
505				mmapprotname ((int)*ip);
506				ip++;
507				narg--;
508			} else if (ktr->ktr_code == SYS_madvise) {
509				print_number(ip,narg,c);
510				print_number(ip,narg,c);
511				(void)putchar(',');
512				madvisebehavname((int)*ip);
513				ip++;
514				narg--;
515			} else if (ktr->ktr_code == SYS_setpriority) {
516				print_number(ip,narg,c);
517				print_number(ip,narg,c);
518				(void)putchar(',');
519				prioname((int)*ip);
520				ip++;
521				narg--;
522			} else if (ktr->ktr_code == SYS_fcntl) {
523				int cmd;
524				int arg;
525				print_number(ip,narg,c);
526				cmd = *ip;
527				arg = *++ip;
528				(void)putchar(',');
529				fcntlcmdname(cmd, arg, decimal);
530				ip++;
531				narg-=2;
532			} else if (ktr->ktr_code == SYS_socket) {
533				int sockdomain;
534				(void)putchar('(');
535				sockdomain=(int)*ip;
536				sockdomainname(sockdomain);
537				ip++;
538				narg--;
539				(void)putchar(',');
540				socktypename((int)*ip);
541				ip++;
542				narg--;
543				if (sockdomain == PF_INET ||
544				    sockdomain == PF_INET6) {
545					(void)putchar(',');
546					sockipprotoname((int)*ip);
547					ip++;
548					narg--;
549				}
550				c = ',';
551			} else if (ktr->ktr_code == SYS_setsockopt ||
552				   ktr->ktr_code == SYS_getsockopt) {
553				print_number(ip,narg,c);
554				(void)putchar(',');
555				sockoptlevelname((int)*ip, decimal);
556				ip++;
557				narg--;
558				(void)putchar(',');
559				sockoptname((int)*ip);
560				ip++;
561				narg--;
562			} else if (ktr->ktr_code == SYS_lseek) {
563				print_number(ip,narg,c);
564				/* Hidden 'pad' argument, not in lseek(2) */
565				print_number(ip,narg,c);
566				print_number(ip,narg,c);
567				(void)putchar(',');
568				whencename ((int)*ip);
569				ip++;
570				narg--;
571			} else if (ktr->ktr_code == SYS_flock) {
572				print_number(ip,narg,c);
573				(void)putchar(',');
574				flockname((int)*ip);
575				ip++;
576				narg--;
577			} else if (ktr->ktr_code == SYS_mkfifo ||
578				   ktr->ktr_code == SYS_mkdir) {
579				print_number(ip,narg,c);
580				(void)putchar(',');
581				modename((int)*ip);
582				ip++;
583				narg--;
584			} else if (ktr->ktr_code == SYS_shutdown) {
585				print_number(ip,narg,c);
586				(void)putchar(',');
587				shutdownhowname((int)*ip);
588				ip++;
589				narg--;
590			} else if (ktr->ktr_code == SYS_socketpair) {
591				(void)putchar('(');
592				sockdomainname((int)*ip);
593				ip++;
594				narg--;
595				(void)putchar(',');
596				socktypename((int)*ip);
597				ip++;
598				narg--;
599				c = ',';
600			} else if (ktr->ktr_code == SYS_getrlimit ||
601				   ktr->ktr_code == SYS_setrlimit) {
602				(void)putchar('(');
603				rlimitname((int)*ip);
604				ip++;
605				narg--;
606				c = ',';
607			} else if (ktr->ktr_code == SYS_quotactl) {
608				print_number(ip,narg,c);
609				quotactlname((int)*ip);
610				ip++;
611				narg--;
612				c = ',';
613			} else if (ktr->ktr_code == SYS_nfssvc) {
614				(void)putchar('(');
615				nfssvcname((int)*ip);
616				ip++;
617				narg--;
618				c = ',';
619			} else if (ktr->ktr_code == SYS_rtprio) {
620				(void)putchar('(');
621				rtprioname((int)*ip);
622				ip++;
623				narg--;
624				c = ',';
625			} else if (ktr->ktr_code == SYS___semctl) {
626				print_number(ip,narg,c);
627				print_number(ip,narg,c);
628				semctlname((int)*ip);
629				ip++;
630				narg--;
631			} else if (ktr->ktr_code == SYS_semget) {
632				print_number(ip,narg,c);
633				print_number(ip,narg,c);
634				semgetname((int)*ip);
635				ip++;
636				narg--;
637			} else if (ktr->ktr_code == SYS_msgctl) {
638				print_number(ip,narg,c);
639				shmctlname((int)*ip);
640				ip++;
641				narg--;
642			} else if (ktr->ktr_code == SYS_shmat) {
643				print_number(ip,narg,c);
644				print_number(ip,narg,c);
645				shmatname((int)*ip);
646				ip++;
647				narg--;
648			} else if (ktr->ktr_code == SYS_shmctl) {
649				print_number(ip,narg,c);
650				shmctlname((int)*ip);
651				ip++;
652				narg--;
653			} else if (ktr->ktr_code == SYS_minherit) {
654				print_number(ip,narg,c);
655				print_number(ip,narg,c);
656				minheritname((int)*ip);
657				ip++;
658				narg--;
659			} else if (ktr->ktr_code == SYS_rfork) {
660				(void)putchar('(');
661				rforkname((int)*ip);
662				ip++;
663				narg--;
664				c = ',';
665			} else if (ktr->ktr_code == SYS_lio_listio) {
666				(void)putchar('(');
667				lio_listioname((int)*ip);
668				ip++;
669				narg--;
670				c = ',';
671			} else if (ktr->ktr_code == SYS_mlockall) {
672				(void)putchar('(');
673				mlockallname((int)*ip);
674				ip++;
675				narg--;
676			} else if (ktr->ktr_code == SYS_sched_setscheduler) {
677				print_number(ip,narg,c);
678				schedpolicyname((int)*ip);
679				ip++;
680				narg--;
681			} else if (ktr->ktr_code == SYS_sched_get_priority_max ||
682				   ktr->ktr_code == SYS_sched_get_priority_min) {
683				(void)putchar('(');
684				schedpolicyname((int)*ip);
685				ip++;
686				narg--;
687			} else if (ktr->ktr_code == SYS_sendfile) {
688				print_number(ip,narg,c);
689				print_number(ip,narg,c);
690				print_number(ip,narg,c);
691				print_number(ip,narg,c);
692				print_number(ip,narg,c);
693				print_number(ip,narg,c);
694				sendfileflagsname((int)*ip);
695				ip++;
696				narg--;
697			} else if (ktr->ktr_code == SYS_kldsym) {
698				print_number(ip,narg,c);
699				kldsymcmdname((int)*ip);
700				ip++;
701				narg--;
702			} else if (ktr->ktr_code == SYS_sigprocmask) {
703				(void)putchar('(');
704				sigprocmaskhowname((int)*ip);
705				ip++;
706				narg--;
707				c = ',';
708			} else if (ktr->ktr_code == SYS___acl_get_file ||
709				   ktr->ktr_code == SYS___acl_set_file ||
710				   ktr->ktr_code == SYS___acl_get_fd ||
711				   ktr->ktr_code == SYS___acl_set_fd ||
712				   ktr->ktr_code == SYS___acl_delete_file ||
713				   ktr->ktr_code == SYS___acl_delete_fd ||
714				   ktr->ktr_code == SYS___acl_aclcheck_file ||
715				   ktr->ktr_code == SYS___acl_aclcheck_fd ||
716				   ktr->ktr_code == SYS___acl_get_link ||
717				   ktr->ktr_code == SYS___acl_set_link ||
718				   ktr->ktr_code == SYS___acl_delete_link ||
719				   ktr->ktr_code == SYS___acl_aclcheck_link) {
720				print_number(ip,narg,c);
721				acltypename((int)*ip);
722				ip++;
723				narg--;
724			} else if (ktr->ktr_code == SYS_sigaction) {
725				(void)putchar('(');
726				signame((int)*ip);
727				ip++;
728				narg--;
729				c = ',';
730			} else if (ktr->ktr_code == SYS_extattrctl) {
731				print_number(ip,narg,c);
732				extattrctlname((int)*ip);
733				ip++;
734				narg--;
735			} else if (ktr->ktr_code == SYS_nmount) {
736				print_number(ip,narg,c);
737				print_number(ip,narg,c);
738				(void)putchar(',');
739				mountflagsname ((int)*ip);
740				ip++;
741				narg--;
742			} else if (ktr->ktr_code == SYS_kse_thr_interrupt) {
743				print_number(ip,narg,c);
744				(void)putchar(',');
745				ksethrcmdname ((int)*ip);
746				ip++;
747				narg--;
748			} else if (ktr->ktr_code == SYS_thr_create) {
749				print_number(ip,narg,c);
750				print_number(ip,narg,c);
751				(void)putchar(',');
752				thrcreateflagsname ((int)*ip);
753				ip++;
754				narg--;
755			} else if (ktr->ktr_code == SYS_thr_kill) {
756				print_number(ip,narg,c);
757				(void)putchar(',');
758				signame ((int)*ip);
759				ip++;
760				narg--;
761			} else if (ktr->ktr_code == SYS_kldunloadf) {
762				print_number(ip,narg,c);
763				(void)putchar(',');
764				kldunloadfflagsname ((int)*ip);
765				ip++;
766				narg--;
767			}
768		}
769		while (narg) {
770			print_number(ip,narg,c);
771		}
772		(void)putchar(')');
773	}
774	(void)putchar('\n');
775}
776
777void
778ktrsysret(struct ktr_sysret *ktr)
779{
780	register_t ret = ktr->ktr_retval;
781	int error = ktr->ktr_error;
782	int code = ktr->ktr_code;
783
784	if (code >= nsyscalls || code < 0)
785		(void)printf("[%d] ", code);
786	else
787		(void)printf("%s ", syscallnames[code]);
788
789	if (error == 0) {
790		if (fancy) {
791			(void)printf("%d", ret);
792			if (ret < 0 || ret > 9)
793				(void)printf("/%#lx", (long)ret);
794		} else {
795			if (decimal)
796				(void)printf("%ld", (long)ret);
797			else
798				(void)printf("%#lx", (long)ret);
799		}
800	} else if (error == ERESTART)
801		(void)printf("RESTART");
802	else if (error == EJUSTRETURN)
803		(void)printf("JUSTRETURN");
804	else {
805		(void)printf("-1 errno %d", ktr->ktr_error);
806		if (fancy)
807			(void)printf(" %s", strerror(ktr->ktr_error));
808	}
809	(void)putchar('\n');
810}
811
812void
813ktrnamei(char *cp, int len)
814{
815	(void)printf("\"%.*s\"\n", len, cp);
816}
817
818void
819hexdump(char *p, int len, int screenwidth)
820{
821	int n, i;
822	int width;
823
824	width = 0;
825	do {
826		width += 2;
827		i = 13;			/* base offset */
828		i += (width / 2) + 1;	/* spaces every second byte */
829		i += (width * 2);	/* width of bytes */
830		i += 3;			/* "  |" */
831		i += width;		/* each byte */
832		i += 1;			/* "|" */
833	} while (i < screenwidth);
834	width -= 2;
835
836	for (n = 0; n < len; n += width) {
837		for (i = n; i < n + width; i++) {
838			if ((i % width) == 0) {	/* beginning of line */
839				printf("       0x%04x", i);
840			}
841			if ((i % 2) == 0) {
842				printf(" ");
843			}
844			if (i < len)
845				printf("%02x", p[i] & 0xff);
846			else
847				printf("  ");
848		}
849		printf("  |");
850		for (i = n; i < n + width; i++) {
851			if (i >= len)
852				break;
853			if (p[i] >= ' ' && p[i] <= '~')
854				printf("%c", p[i]);
855			else
856				printf(".");
857		}
858		printf("|\n");
859	}
860	if ((i % width) != 0)
861		printf("\n");
862}
863
864void
865visdump(char *dp, int datalen, int screenwidth)
866{
867	int col = 0;
868	char *cp;
869	int width;
870	char visbuf[5];
871
872	(void)printf("       \"");
873	col = 8;
874	for (;datalen > 0; datalen--, dp++) {
875		(void) vis(visbuf, *dp, VIS_CSTYLE, *(dp+1));
876		cp = visbuf;
877		/*
878		 * Keep track of printables and
879		 * space chars (like fold(1)).
880		 */
881		if (col == 0) {
882			(void)putchar('\t');
883			col = 8;
884		}
885		switch(*cp) {
886		case '\n':
887			col = 0;
888			(void)putchar('\n');
889			continue;
890		case '\t':
891			width = 8 - (col&07);
892			break;
893		default:
894			width = strlen(cp);
895		}
896		if (col + width > (screenwidth-2)) {
897			(void)printf("\\\n\t");
898			col = 8;
899		}
900		col += width;
901		do {
902			(void)putchar(*cp++);
903		} while (*cp);
904	}
905	if (col == 0)
906		(void)printf("       ");
907	(void)printf("\"\n");
908}
909
910void
911ktrgenio(struct ktr_genio *ktr, int len)
912{
913	int datalen = len - sizeof (struct ktr_genio);
914	char *dp = (char *)ktr + sizeof (struct ktr_genio);
915	static int screenwidth = 0;
916	int i, binary;
917
918	if (screenwidth == 0) {
919		struct winsize ws;
920
921		if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 &&
922		    ws.ws_col > 8)
923			screenwidth = ws.ws_col;
924		else
925			screenwidth = 80;
926	}
927	printf("fd %d %s %d byte%s\n", ktr->ktr_fd,
928		ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen,
929		datalen == 1 ? "" : "s");
930	if (suppressdata)
931		return;
932	if (maxdata && datalen > maxdata)
933		datalen = maxdata;
934
935	for (i = 0, binary = 0; i < datalen && binary == 0; i++)  {
936		if (dp[i] >= 32 && dp[i] < 127)
937			continue;
938		if (dp[i] == 10 || dp[i] == 13 || dp[i] == 0 || dp[i] == 9)
939			continue;
940		binary = 1;
941	}
942	if (binary)
943		hexdump(dp, datalen, screenwidth);
944	else
945		visdump(dp, datalen, screenwidth);
946}
947
948const char *signames[] = {
949	"NULL", "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT",	/*  1 - 6  */
950	"EMT", "FPE", "KILL", "BUS", "SEGV", "SYS",		/*  7 - 12 */
951	"PIPE", "ALRM",  "TERM", "URG", "STOP", "TSTP",		/* 13 - 18 */
952	"CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU",		/* 19 - 24 */
953	"XFSZ", "VTALRM", "PROF", "WINCH", "29", "USR1",	/* 25 - 30 */
954	"USR2", NULL,						/* 31 - 32 */
955};
956
957void
958ktrpsig(struct ktr_psig *psig)
959{
960	if (psig->signo > 0 && psig->signo < NSIG)
961		(void)printf("SIG%s ", signames[psig->signo]);
962	else
963		(void)printf("SIG %d ", psig->signo);
964	if (psig->action == SIG_DFL)
965		(void)printf("SIG_DFL\n");
966	else {
967		(void)printf("caught handler=0x%lx mask=0x%x code=0x%x\n",
968		    (u_long)psig->action, psig->mask.__bits[0], psig->code);
969	}
970}
971
972void
973ktrcsw(struct ktr_csw *cs)
974{
975	(void)printf("%s %s\n", cs->out ? "stop" : "resume",
976		cs->user ? "user" : "kernel");
977}
978
979#define	UTRACE_DLOPEN_START		1
980#define	UTRACE_DLOPEN_STOP		2
981#define	UTRACE_DLCLOSE_START		3
982#define	UTRACE_DLCLOSE_STOP		4
983#define	UTRACE_LOAD_OBJECT		5
984#define	UTRACE_UNLOAD_OBJECT		6
985#define	UTRACE_ADD_RUNDEP		7
986#define	UTRACE_PRELOAD_FINISHED		8
987#define	UTRACE_INIT_CALL		9
988#define	UTRACE_FINI_CALL		10
989
990struct utrace_rtld {
991	char sig[4];				/* 'RTLD' */
992	int event;
993	void *handle;
994	void *mapbase;
995	size_t mapsize;
996	int refcnt;
997	char name[MAXPATHLEN];
998};
999
1000void
1001ktruser_rtld(int len, unsigned char *p)
1002{
1003	struct utrace_rtld *ut = (struct utrace_rtld *)p;
1004	void *parent;
1005	int mode;
1006
1007	switch (ut->event) {
1008	case UTRACE_DLOPEN_START:
1009		mode = ut->refcnt;
1010		printf("dlopen(%s, ", ut->name);
1011		switch (mode & RTLD_MODEMASK) {
1012		case RTLD_NOW:
1013			printf("RTLD_NOW");
1014			break;
1015		case RTLD_LAZY:
1016			printf("RTLD_LAZY");
1017			break;
1018		default:
1019			printf("%#x", mode & RTLD_MODEMASK);
1020		}
1021		if (mode & RTLD_GLOBAL)
1022			printf(" | RTLD_GLOBAL");
1023		if (mode & RTLD_TRACE)
1024			printf(" | RTLD_TRACE");
1025		if (mode & ~(RTLD_MODEMASK | RTLD_GLOBAL | RTLD_TRACE))
1026			printf(" | %#x", mode &
1027			    ~(RTLD_MODEMASK | RTLD_GLOBAL | RTLD_TRACE));
1028		printf(")\n");
1029		break;
1030	case UTRACE_DLOPEN_STOP:
1031		printf("%p = dlopen(%s) ref %d\n", ut->handle, ut->name,
1032		    ut->refcnt);
1033		break;
1034	case UTRACE_DLCLOSE_START:
1035		printf("dlclose(%p) (%s, %d)\n", ut->handle, ut->name,
1036		    ut->refcnt);
1037		break;
1038	case UTRACE_DLCLOSE_STOP:
1039		printf("dlclose(%p) finished\n", ut->handle);
1040		break;
1041	case UTRACE_LOAD_OBJECT:
1042		printf("RTLD: loaded   %p @ %p - %p (%s)\n", ut->handle,
1043		    ut->mapbase, (char *)ut->mapbase + ut->mapsize - 1,
1044		    ut->name);
1045		break;
1046	case UTRACE_UNLOAD_OBJECT:
1047		printf("RTLD: unloaded %p @ %p - %p (%s)\n", ut->handle,
1048		    ut->mapbase, (char *)ut->mapbase + ut->mapsize - 1,
1049		    ut->name);
1050		break;
1051	case UTRACE_ADD_RUNDEP:
1052		parent = ut->mapbase;
1053		printf("RTLD: %p now depends on %p (%s, %d)\n", parent,
1054		    ut->handle, ut->name, ut->refcnt);
1055		break;
1056	case UTRACE_PRELOAD_FINISHED:
1057		printf("RTLD: LD_PRELOAD finished\n");
1058		break;
1059	case UTRACE_INIT_CALL:
1060		printf("RTLD: init %p for %p (%s)\n", ut->mapbase, ut->handle,
1061		    ut->name);
1062		break;
1063	case UTRACE_FINI_CALL:
1064		printf("RTLD: fini %p for %p (%s)\n", ut->mapbase, ut->handle,
1065		    ut->name);
1066		break;
1067	default:
1068		p += 4;
1069		len -= 4;
1070		printf("RTLD: %d ", len);
1071		while (len--)
1072			if (decimal)
1073				printf(" %d", *p++);
1074			else
1075				printf(" %02x", *p++);
1076		printf("\n");
1077	}
1078}
1079
1080struct utrace_malloc {
1081	void *p;
1082	size_t s;
1083	void *r;
1084};
1085
1086void
1087ktruser_malloc(int len, unsigned char *p)
1088{
1089	struct utrace_malloc *ut = (struct utrace_malloc *)p;
1090
1091	if (ut->p == NULL) {
1092		if (ut->s == 0 && ut->r == NULL)
1093			printf("malloc_init()\n");
1094		else
1095			printf("%p = malloc(%zu)\n", ut->r, ut->s);
1096	} else {
1097		if (ut->s == 0)
1098			printf("free(%p)\n", ut->p);
1099		else
1100			printf("%p = realloc(%p, %zu)\n", ut->r, ut->p, ut->s);
1101	}
1102}
1103
1104void
1105ktruser(int len, unsigned char *p)
1106{
1107
1108	if (len >= 8 && bcmp(p, "RTLD", 4) == 0) {
1109		ktruser_rtld(len, p);
1110		return;
1111	}
1112
1113	if (len == sizeof(struct utrace_malloc)) {
1114		ktruser_malloc(len, p);
1115		return;
1116	}
1117
1118	(void)printf("%d ", len);
1119	while (len--)
1120		if (decimal)
1121			(void)printf(" %d", *p++);
1122		else
1123			(void)printf(" %02x", *p++);
1124	(void)printf("\n");
1125}
1126
1127void
1128usage(void)
1129{
1130	(void)fprintf(stderr,
1131  "usage: kdump [-dEnlHRsT] [-f trfile] [-m maxdata] [-p pid] [-t [cnisuw]]\n");
1132	exit(1);
1133}
1134