kdump.c revision 189707
11590Srgrimes/*-
21590Srgrimes * Copyright (c) 1988, 1993
31590Srgrimes *	The Regents of the University of California.  All rights reserved.
41590Srgrimes *
51590Srgrimes * Redistribution and use in source and binary forms, with or without
61590Srgrimes * modification, are permitted provided that the following conditions
71590Srgrimes * are met:
81590Srgrimes * 1. Redistributions of source code must retain the above copyright
91590Srgrimes *    notice, this list of conditions and the following disclaimer.
101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111590Srgrimes *    notice, this list of conditions and the following disclaimer in the
121590Srgrimes *    documentation and/or other materials provided with the distribution.
131590Srgrimes * 3. All advertising materials mentioning features or use of this software
141590Srgrimes *    must display the following acknowledgement:
151590Srgrimes *	This product includes software developed by the University of
161590Srgrimes *	California, Berkeley and its contributors.
171590Srgrimes * 4. Neither the name of the University nor the names of its contributors
181590Srgrimes *    may be used to endorse or promote products derived from this software
191590Srgrimes *    without specific prior written permission.
201590Srgrimes *
211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311590Srgrimes * SUCH DAMAGE.
321590Srgrimes */
331590Srgrimes
341590Srgrimes#ifndef lint
3527443Scharnierstatic const char copyright[] =
361590Srgrimes"@(#) Copyright (c) 1988, 1993\n\
371590Srgrimes	The Regents of the University of California.  All rights reserved.\n";
381590Srgrimes#endif /* not lint */
391590Srgrimes
401590Srgrimes#ifndef lint
4127443Scharnier#if 0
421590Srgrimesstatic char sccsid[] = "@(#)kdump.c	8.1 (Berkeley) 6/6/93";
4327443Scharnier#endif
441590Srgrimes#endif /* not lint */
4599112Sobrien#include <sys/cdefs.h>
4699112Sobrien__FBSDID("$FreeBSD: head/usr.bin/kdump/kdump.c 189707 2009-03-11 21:48:36Z jhb $");
471590Srgrimes
4855206Speter#define _KERNEL
492215Scsgrextern int errno;
502215Scsgr#include <sys/errno.h>
5155206Speter#undef _KERNEL
521590Srgrimes#include <sys/param.h>
531590Srgrimes#include <sys/errno.h>
54100824Sdwmalone#define _KERNEL
551590Srgrimes#include <sys/time.h>
56100824Sdwmalone#undef _KERNEL
571590Srgrimes#include <sys/uio.h>
581590Srgrimes#include <sys/ktrace.h>
591590Srgrimes#include <sys/ioctl.h>
60165758Srodrigc#include <sys/socket.h>
61176471Sdes#include <sys/stat.h>
62176471Sdes#include <sys/un.h>
63176471Sdes#ifdef IPX
64176471Sdes#include <sys/types.h>
65176471Sdes#include <netipx/ipx.h>
66176471Sdes#endif
67176471Sdes#ifdef NETATALK
68176471Sdes#include <netatalk/at.h>
69176471Sdes#endif
70176471Sdes#include <netinet/in.h>
71165916Sjhb#include <dlfcn.h>
7227443Scharnier#include <err.h>
73176471Sdes#include <grp.h>
74176471Sdes#include <inttypes.h>
7527443Scharnier#include <locale.h>
76176471Sdes#include <pwd.h>
771590Srgrimes#include <stdio.h>
781590Srgrimes#include <stdlib.h>
791590Srgrimes#include <string.h>
80176471Sdes#include <time.h>
8127443Scharnier#include <unistd.h>
8227443Scharnier#include <vis.h>
831590Srgrimes#include "ktrace.h"
84158766Snetchild#include "kdump_subr.h"
851590Srgrimes
86100824Sdwmaloneint fread_tail(void *, int, int);
87100824Sdwmalonevoid dumpheader(struct ktr_header *);
88100824Sdwmalonevoid ktrsyscall(struct ktr_syscall *);
89100824Sdwmalonevoid ktrsysret(struct ktr_sysret *);
90100824Sdwmalonevoid ktrnamei(char *, int);
91115759Spetervoid hexdump(char *, int, int);
92115759Spetervoid visdump(char *, int, int);
93100824Sdwmalonevoid ktrgenio(struct ktr_genio *, int);
94100824Sdwmalonevoid ktrpsig(struct ktr_psig *);
95100824Sdwmalonevoid ktrcsw(struct ktr_csw *);
96100824Sdwmalonevoid ktruser(int, unsigned char *);
97176471Sdesvoid ktrsockaddr(struct sockaddr *);
98176471Sdesvoid ktrstat(struct stat *);
99176471Sdesvoid ktrstruct(char *, size_t);
100100824Sdwmalonevoid usage(void);
101135466Sruconst char *ioctlname(u_long);
102100824Sdwmalone
103176471Sdesint timestamp, decimal, fancy = 1, suppressdata, tail, threads, maxdata,
104176471Sdes    resolv = 0;
105100824Sdwmaloneconst char *tracefile = DEF_TRACEFILE;
1061590Srgrimesstruct ktr_header ktr_header;
1071590Srgrimes
108176471Sdes#define TIME_FORMAT	"%b %e %T %Y"
1091590Srgrimes#define eqs(s1, s2)	(strcmp((s1), (s2)) == 0)
1101590Srgrimes
111100824Sdwmaloneint
112100824Sdwmalonemain(int argc, char *argv[])
1131590Srgrimes{
1141590Srgrimes	int ch, ktrlen, size;
115100824Sdwmalone	void *m;
1161590Srgrimes	int trpoints = ALL_POINTS;
117112201Sjhb	int drop_logged;
118115759Speter	pid_t pid = 0;
1191590Srgrimes
12011823Sache	(void) setlocale(LC_CTYPE, "");
12111823Sache
122176471Sdes	while ((ch = getopt(argc,argv,"f:dElm:np:HRrsTt:")) != -1)
1231590Srgrimes		switch((char)ch) {
1241590Srgrimes		case 'f':
1251590Srgrimes			tracefile = optarg;
1261590Srgrimes			break;
1271590Srgrimes		case 'd':
1281590Srgrimes			decimal = 1;
1291590Srgrimes			break;
1301590Srgrimes		case 'l':
1311590Srgrimes			tail = 1;
1321590Srgrimes			break;
1331590Srgrimes		case 'm':
1341590Srgrimes			maxdata = atoi(optarg);
1351590Srgrimes			break;
1361590Srgrimes		case 'n':
1371590Srgrimes			fancy = 0;
1381590Srgrimes			break;
139115759Speter		case 'p':
140115759Speter			pid = atoi(optarg);
141115759Speter			break;
142176471Sdes		case 'r':
143176471Sdes			resolv = 1;
144176471Sdes			break;
145152331Srwatson		case 's':
146152331Srwatson			suppressdata = 1;
147152331Srwatson			break;
148123187Speter		case 'E':
149123187Speter			timestamp = 3;	/* elapsed timestamp */
150123187Speter			break;
151151930Srwatson		case 'H':
152151930Srwatson			threads = 1;
153151930Srwatson			break;
1541590Srgrimes		case 'R':
1551590Srgrimes			timestamp = 2;	/* relative timestamp */
1561590Srgrimes			break;
1571590Srgrimes		case 'T':
1581590Srgrimes			timestamp = 1;
1591590Srgrimes			break;
1601590Srgrimes		case 't':
1611590Srgrimes			trpoints = getpoints(optarg);
16227443Scharnier			if (trpoints < 0)
16327443Scharnier				errx(1, "unknown trace point in %s", optarg);
1641590Srgrimes			break;
1651590Srgrimes		default:
1661590Srgrimes			usage();
1671590Srgrimes		}
1681590Srgrimes
16919853Sfenner	if (argc > optind)
1701590Srgrimes		usage();
1711590Srgrimes
1721590Srgrimes	m = (void *)malloc(size = 1025);
17327443Scharnier	if (m == NULL)
17427443Scharnier		errx(1, "%s", strerror(ENOMEM));
17527443Scharnier	if (!freopen(tracefile, "r", stdin))
17627443Scharnier		err(1, "%s", tracefile);
177112201Sjhb	drop_logged = 0;
1781590Srgrimes	while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) {
179112201Sjhb		if (ktr_header.ktr_type & KTR_DROP) {
180112201Sjhb			ktr_header.ktr_type &= ~KTR_DROP;
181151930Srwatson			if (!drop_logged && threads) {
182151930Srwatson				(void)printf("%6d %6d %-8.*s Events dropped.\n",
183151930Srwatson				    ktr_header.ktr_pid, ktr_header.ktr_tid >
184151930Srwatson				    0 ? ktr_header.ktr_tid : 0, MAXCOMLEN,
185151930Srwatson				    ktr_header.ktr_comm);
186151930Srwatson				drop_logged = 1;
187151930Srwatson			} else if (!drop_logged) {
188112201Sjhb				(void)printf("%6d %-8.*s Events dropped.\n",
189112201Sjhb				    ktr_header.ktr_pid, MAXCOMLEN,
190112201Sjhb				    ktr_header.ktr_comm);
191112201Sjhb				drop_logged = 1;
192112201Sjhb			}
193112201Sjhb		}
1941590Srgrimes		if (trpoints & (1<<ktr_header.ktr_type))
195115759Speter			if (pid == 0 || ktr_header.ktr_pid == pid)
196115759Speter				dumpheader(&ktr_header);
19727443Scharnier		if ((ktrlen = ktr_header.ktr_len) < 0)
19827443Scharnier			errx(1, "bogus length 0x%x", ktrlen);
1991590Srgrimes		if (ktrlen > size) {
2001590Srgrimes			m = (void *)realloc(m, ktrlen+1);
20127443Scharnier			if (m == NULL)
20227443Scharnier				errx(1, "%s", strerror(ENOMEM));
2031590Srgrimes			size = ktrlen;
2041590Srgrimes		}
20527443Scharnier		if (ktrlen && fread_tail(m, ktrlen, 1) == 0)
20627443Scharnier			errx(1, "data too short");
207115759Speter		if (pid && ktr_header.ktr_pid != pid)
208115759Speter			continue;
2091590Srgrimes		if ((trpoints & (1<<ktr_header.ktr_type)) == 0)
2101590Srgrimes			continue;
211112201Sjhb		drop_logged = 0;
2121590Srgrimes		switch (ktr_header.ktr_type) {
2131590Srgrimes		case KTR_SYSCALL:
2141590Srgrimes			ktrsyscall((struct ktr_syscall *)m);
2151590Srgrimes			break;
2161590Srgrimes		case KTR_SYSRET:
2171590Srgrimes			ktrsysret((struct ktr_sysret *)m);
2181590Srgrimes			break;
2191590Srgrimes		case KTR_NAMEI:
220189707Sjhb		case KTR_SYSCTL:
2211590Srgrimes			ktrnamei(m, ktrlen);
2221590Srgrimes			break;
2231590Srgrimes		case KTR_GENIO:
2241590Srgrimes			ktrgenio((struct ktr_genio *)m, ktrlen);
2251590Srgrimes			break;
2261590Srgrimes		case KTR_PSIG:
2271590Srgrimes			ktrpsig((struct ktr_psig *)m);
2281590Srgrimes			break;
2291590Srgrimes		case KTR_CSW:
2301590Srgrimes			ktrcsw((struct ktr_csw *)m);
2311590Srgrimes			break;
23218400Sphk		case KTR_USER:
23318470Sphk			ktruser(ktrlen, m);
23418400Sphk			break;
235176471Sdes		case KTR_STRUCT:
236176471Sdes			ktrstruct(m, ktrlen);
237176471Sdes			break;
238112203Sjhb		default:
239112203Sjhb			printf("\n");
240112203Sjhb			break;
2411590Srgrimes		}
2421590Srgrimes		if (tail)
2431590Srgrimes			(void)fflush(stdout);
2441590Srgrimes	}
245100824Sdwmalone	return 0;
2461590Srgrimes}
2471590Srgrimes
248100824Sdwmaloneint
249100824Sdwmalonefread_tail(void *buf, int size, int num)
2501590Srgrimes{
2511590Srgrimes	int i;
2521590Srgrimes
2531590Srgrimes	while ((i = fread(buf, size, num, stdin)) == 0 && tail) {
2541590Srgrimes		(void)sleep(1);
2551590Srgrimes		clearerr(stdin);
2561590Srgrimes	}
2571590Srgrimes	return (i);
2581590Srgrimes}
2591590Srgrimes
260100824Sdwmalonevoid
261100824Sdwmalonedumpheader(struct ktr_header *kth)
2621590Srgrimes{
2631590Srgrimes	static char unknown[64];
2641590Srgrimes	static struct timeval prevtime, temp;
265100824Sdwmalone	const char *type;
2661590Srgrimes
2671590Srgrimes	switch (kth->ktr_type) {
2681590Srgrimes	case KTR_SYSCALL:
2691590Srgrimes		type = "CALL";
2701590Srgrimes		break;
2711590Srgrimes	case KTR_SYSRET:
2721590Srgrimes		type = "RET ";
2731590Srgrimes		break;
2741590Srgrimes	case KTR_NAMEI:
2751590Srgrimes		type = "NAMI";
2761590Srgrimes		break;
2771590Srgrimes	case KTR_GENIO:
2781590Srgrimes		type = "GIO ";
2791590Srgrimes		break;
2801590Srgrimes	case KTR_PSIG:
2811590Srgrimes		type = "PSIG";
2821590Srgrimes		break;
2831590Srgrimes	case KTR_CSW:
284171333Sjhb		type = "CSW ";
2851590Srgrimes		break;
28618400Sphk	case KTR_USER:
28718400Sphk		type = "USER";
28818400Sphk		break;
289176471Sdes	case KTR_STRUCT:
290176471Sdes		type = "STRU";
291176471Sdes		break;
292189707Sjhb	case KTR_SYSCTL:
293189707Sjhb		type = "SCTL";
294189707Sjhb		break;
2951590Srgrimes	default:
2961590Srgrimes		(void)sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type);
2971590Srgrimes		type = unknown;
2981590Srgrimes	}
2991590Srgrimes
300151930Srwatson	/*
301151930Srwatson	 * The ktr_tid field was previously the ktr_buffer field, which held
302151930Srwatson	 * the kernel pointer value for the buffer associated with data
303151930Srwatson	 * following the record header.  It now holds a threadid, but only
304151930Srwatson	 * for trace files after the change.  Older trace files still contain
305151930Srwatson	 * kernel pointers.  Detect this and suppress the results by printing
306151930Srwatson	 * negative tid's as 0.
307151930Srwatson	 */
308151930Srwatson	if (threads)
309151930Srwatson		(void)printf("%6d %6d %-8.*s ", kth->ktr_pid, kth->ktr_tid >
310151930Srwatson		    0 ? kth->ktr_tid : 0, MAXCOMLEN, kth->ktr_comm);
311151930Srwatson	else
312151930Srwatson		(void)printf("%6d %-8.*s ", kth->ktr_pid, MAXCOMLEN,
313151930Srwatson		    kth->ktr_comm);
3141590Srgrimes	if (timestamp) {
315123187Speter		if (timestamp == 3) {
316123187Speter			if (prevtime.tv_sec == 0)
317123187Speter				prevtime = kth->ktr_time;
318123187Speter			timevalsub(&kth->ktr_time, &prevtime);
319123187Speter		}
3201590Srgrimes		if (timestamp == 2) {
3211590Srgrimes			temp = kth->ktr_time;
3221590Srgrimes			timevalsub(&kth->ktr_time, &prevtime);
3231590Srgrimes			prevtime = temp;
3241590Srgrimes		}
3251590Srgrimes		(void)printf("%ld.%06ld ",
3261590Srgrimes		    kth->ktr_time.tv_sec, kth->ktr_time.tv_usec);
3271590Srgrimes	}
3281590Srgrimes	(void)printf("%s  ", type);
3291590Srgrimes}
3301590Srgrimes
3311590Srgrimes#include <sys/syscall.h>
3321590Srgrimes#define KTRACE
3334721Sphk#include <sys/kern/syscalls.c>
3341590Srgrimes#undef KTRACE
3351590Srgrimesint nsyscalls = sizeof (syscallnames) / sizeof (syscallnames[0]);
3361590Srgrimes
337100824Sdwmalonevoid
338100824Sdwmalonektrsyscall(struct ktr_syscall *ktr)
3391590Srgrimes{
340100824Sdwmalone	int narg = ktr->ktr_narg;
341100824Sdwmalone	register_t *ip;
3421590Srgrimes
3431590Srgrimes	if (ktr->ktr_code >= nsyscalls || ktr->ktr_code < 0)
3441590Srgrimes		(void)printf("[%d]", ktr->ktr_code);
3451590Srgrimes	else
3461590Srgrimes		(void)printf("%s", syscallnames[ktr->ktr_code]);
34747957Sdt	ip = &ktr->ktr_args[0];
3481590Srgrimes	if (narg) {
3491590Srgrimes		char c = '(';
3501590Srgrimes		if (fancy) {
351158766Snetchild
352158766Snetchild#define print_number(i,n,c) do {                      \
353158766Snetchild	if (decimal)                                  \
354158766Snetchild		(void)printf("%c%ld", c, (long)*i);   \
355158766Snetchild	else                                          \
356158766Snetchild		(void)printf("%c%#lx", c, (long)*i);  \
357158766Snetchild	i++;                                          \
358158766Snetchild	n--;                                          \
359158766Snetchild	c = ',';                                      \
360158766Snetchild	} while (0);
361158766Snetchild
3621590Srgrimes			if (ktr->ktr_code == SYS_ioctl) {
363100824Sdwmalone				const char *cp;
364158766Snetchild				print_number(ip,narg,c);
3651590Srgrimes				if ((cp = ioctlname(*ip)) != NULL)
3661590Srgrimes					(void)printf(",%s", cp);
3671590Srgrimes				else {
3681590Srgrimes					if (decimal)
36947957Sdt						(void)printf(",%ld", (long)*ip);
3701590Srgrimes					else
37147957Sdt						(void)printf(",%#lx ", (long)*ip);
3721590Srgrimes				}
3731590Srgrimes				c = ',';
3741590Srgrimes				ip++;
3751590Srgrimes				narg--;
3761590Srgrimes			} else if (ktr->ktr_code == SYS_ptrace) {
377168543Semaste				(void)putchar('(');
378168543Semaste				ptraceopname ((int)*ip);
3791590Srgrimes				c = ',';
3801590Srgrimes				ip++;
3811590Srgrimes				narg--;
382158766Snetchild			} else if (ktr->ktr_code == SYS_access ||
383158766Snetchild				   ktr->ktr_code == SYS_eaccess) {
384158766Snetchild				print_number(ip,narg,c);
385158766Snetchild				(void)putchar(',');
386158766Snetchild				accessmodename ((int)*ip);
387158766Snetchild				ip++;
388158766Snetchild				narg--;
389158766Snetchild			} else if (ktr->ktr_code == SYS_open) {
390158766Snetchild				int	flags;
391158766Snetchild				int	mode;
392158766Snetchild				print_number(ip,narg,c);
393158766Snetchild				flags = *ip;
394158766Snetchild				mode = *++ip;
395158766Snetchild				(void)putchar(',');
396158766Snetchild				flagsandmodename (flags, mode, decimal);
397158766Snetchild				ip++;
398158766Snetchild				narg-=2;
399158766Snetchild			} else if (ktr->ktr_code == SYS_wait4) {
400158766Snetchild				print_number(ip,narg,c);
401158766Snetchild				print_number(ip,narg,c);
402158766Snetchild				(void)putchar(',');
403158766Snetchild				wait4optname ((int)*ip);
404158766Snetchild				ip++;
405158766Snetchild				narg--;
406158766Snetchild			} else if (ktr->ktr_code == SYS_chmod ||
407158766Snetchild				   ktr->ktr_code == SYS_fchmod ||
408158766Snetchild				   ktr->ktr_code == SYS_lchmod) {
409158766Snetchild				print_number(ip,narg,c);
410158766Snetchild				(void)putchar(',');
411158766Snetchild				modename ((int)*ip);
412158766Snetchild				ip++;
413158766Snetchild				narg--;
414158766Snetchild			} else if (ktr->ktr_code == SYS_mknod) {
415158766Snetchild				print_number(ip,narg,c);
416158766Snetchild				(void)putchar(',');
417158766Snetchild				modename ((int)*ip);
418158766Snetchild				ip++;
419158766Snetchild				narg--;
420158766Snetchild			} else if (ktr->ktr_code == SYS_getfsstat) {
421158766Snetchild				print_number(ip,narg,c);
422158766Snetchild				print_number(ip,narg,c);
423158766Snetchild				(void)putchar(',');
424158766Snetchild				getfsstatflagsname ((int)*ip);
425158766Snetchild				ip++;
426158766Snetchild				narg--;
427158766Snetchild			} else if (ktr->ktr_code == SYS_mount) {
428158766Snetchild				print_number(ip,narg,c);
429158766Snetchild				print_number(ip,narg,c);
430158766Snetchild				(void)putchar(',');
431158766Snetchild				mountflagsname ((int)*ip);
432158766Snetchild				ip++;
433158766Snetchild				narg--;
434158766Snetchild			} else if (ktr->ktr_code == SYS_unmount) {
435158766Snetchild				print_number(ip,narg,c);
436158766Snetchild				(void)putchar(',');
437158766Snetchild				mountflagsname ((int)*ip);
438158766Snetchild				ip++;
439158766Snetchild				narg--;
440158766Snetchild			} else if (ktr->ktr_code == SYS_recvmsg ||
441158766Snetchild				   ktr->ktr_code == SYS_sendmsg) {
442158766Snetchild				print_number(ip,narg,c);
443158766Snetchild				print_number(ip,narg,c);
444158766Snetchild				(void)putchar(',');
445158766Snetchild				sendrecvflagsname ((int)*ip);
446158766Snetchild				ip++;
447158766Snetchild				narg--;
448158766Snetchild			} else if (ktr->ktr_code == SYS_recvfrom ||
449158766Snetchild				   ktr->ktr_code == SYS_sendto) {
450158766Snetchild				print_number(ip,narg,c);
451158766Snetchild				print_number(ip,narg,c);
452158766Snetchild				print_number(ip,narg,c);
453158766Snetchild				(void)putchar(',');
454158766Snetchild				sendrecvflagsname ((int)*ip);
455158766Snetchild				ip++;
456158766Snetchild				narg--;
457158766Snetchild			} else if (ktr->ktr_code == SYS_chflags ||
458158766Snetchild				   ktr->ktr_code == SYS_fchflags ||
459158766Snetchild				   ktr->ktr_code == SYS_lchflags) {
460158766Snetchild				print_number(ip,narg,c);
461158766Snetchild				(void)putchar(',');
462158766Snetchild				modename((int)*ip);
463158766Snetchild				ip++;
464158766Snetchild				narg--;
465158766Snetchild			} else if (ktr->ktr_code == SYS_kill) {
466158766Snetchild				print_number(ip,narg,c);
467158766Snetchild				(void)putchar(',');
468158766Snetchild				signame((int)*ip);
469158766Snetchild				ip++;
470158766Snetchild				narg--;
471158766Snetchild			} else if (ktr->ktr_code == SYS_reboot) {
472158766Snetchild				(void)putchar('(');
473158766Snetchild				rebootoptname((int)*ip);
474158766Snetchild				ip++;
475158766Snetchild				narg--;
476158766Snetchild			} else if (ktr->ktr_code == SYS_umask) {
477158766Snetchild				(void)putchar('(');
478158766Snetchild				modename((int)*ip);
479158766Snetchild				ip++;
480158766Snetchild				narg--;
481158766Snetchild			} else if (ktr->ktr_code == SYS_msync) {
482158766Snetchild				print_number(ip,narg,c);
483158766Snetchild				print_number(ip,narg,c);
484158766Snetchild				(void)putchar(',');
485158766Snetchild				msyncflagsname((int)*ip);
486158766Snetchild				ip++;
487158766Snetchild				narg--;
488171221Speter#ifdef SYS_freebsd6_mmap
489171221Speter			} else if (ktr->ktr_code == SYS_freebsd6_mmap) {
490171221Speter				print_number(ip,narg,c);
491171221Speter				print_number(ip,narg,c);
492171221Speter				(void)putchar(',');
493171221Speter				mmapprotname ((int)*ip);
494171221Speter				(void)putchar(',');
495171221Speter				ip++;
496171221Speter				narg--;
497171221Speter				mmapflagsname ((int)*ip);
498171221Speter				ip++;
499171221Speter				narg--;
500171221Speter#endif
501158766Snetchild			} else if (ktr->ktr_code == SYS_mmap) {
502158766Snetchild				print_number(ip,narg,c);
503158766Snetchild				print_number(ip,narg,c);
504158766Snetchild				(void)putchar(',');
505158766Snetchild				mmapprotname ((int)*ip);
506158766Snetchild				(void)putchar(',');
507158766Snetchild				ip++;
508158766Snetchild				narg--;
509158766Snetchild				mmapflagsname ((int)*ip);
510158766Snetchild				ip++;
511158766Snetchild				narg--;
512158766Snetchild			} else if (ktr->ktr_code == SYS_mprotect) {
513158766Snetchild				print_number(ip,narg,c);
514158766Snetchild				print_number(ip,narg,c);
515158766Snetchild				(void)putchar(',');
516158766Snetchild				mmapprotname ((int)*ip);
517158766Snetchild				ip++;
518158766Snetchild				narg--;
519158766Snetchild			} else if (ktr->ktr_code == SYS_madvise) {
520158766Snetchild				print_number(ip,narg,c);
521158766Snetchild				print_number(ip,narg,c);
522158766Snetchild				(void)putchar(',');
523158766Snetchild				madvisebehavname((int)*ip);
524158766Snetchild				ip++;
525158766Snetchild				narg--;
526158766Snetchild			} else if (ktr->ktr_code == SYS_setpriority) {
527158766Snetchild				print_number(ip,narg,c);
528158766Snetchild				print_number(ip,narg,c);
529158766Snetchild				(void)putchar(',');
530158766Snetchild				prioname((int)*ip);
531158766Snetchild				ip++;
532158766Snetchild				narg--;
533158766Snetchild			} else if (ktr->ktr_code == SYS_fcntl) {
534158766Snetchild				int cmd;
535158766Snetchild				int arg;
536158766Snetchild				print_number(ip,narg,c);
537158766Snetchild				cmd = *ip;
538158766Snetchild				arg = *++ip;
539158766Snetchild				(void)putchar(',');
540158766Snetchild				fcntlcmdname(cmd, arg, decimal);
541158766Snetchild				ip++;
542158766Snetchild				narg-=2;
543158766Snetchild			} else if (ktr->ktr_code == SYS_socket) {
544165758Srodrigc				int sockdomain;
545158766Snetchild				(void)putchar('(');
546165758Srodrigc				sockdomain=(int)*ip;
547165758Srodrigc				sockdomainname(sockdomain);
548158766Snetchild				ip++;
549158766Snetchild				narg--;
550158766Snetchild				(void)putchar(',');
551158766Snetchild				socktypename((int)*ip);
552158766Snetchild				ip++;
553158766Snetchild				narg--;
554165758Srodrigc				if (sockdomain == PF_INET ||
555165758Srodrigc				    sockdomain == PF_INET6) {
556165758Srodrigc					(void)putchar(',');
557165758Srodrigc					sockipprotoname((int)*ip);
558165758Srodrigc					ip++;
559165758Srodrigc					narg--;
560165758Srodrigc				}
561158766Snetchild				c = ',';
562158766Snetchild			} else if (ktr->ktr_code == SYS_setsockopt ||
563158766Snetchild				   ktr->ktr_code == SYS_getsockopt) {
564158766Snetchild				print_number(ip,narg,c);
565158766Snetchild				(void)putchar(',');
566158766Snetchild				sockoptlevelname((int)*ip, decimal);
567175138Sjhb				if ((int)*ip == SOL_SOCKET) {
568175138Sjhb					ip++;
569175138Sjhb					narg--;
570175138Sjhb					(void)putchar(',');
571175138Sjhb					sockoptname((int)*ip);
572175138Sjhb				}
573158766Snetchild				ip++;
574158766Snetchild				narg--;
575171221Speter#ifdef SYS_freebsd6_lseek
576171221Speter			} else if (ktr->ktr_code == SYS_freebsd6_lseek) {
577158766Snetchild				print_number(ip,narg,c);
578158766Snetchild				/* Hidden 'pad' argument, not in lseek(2) */
579158766Snetchild				print_number(ip,narg,c);
580158766Snetchild				print_number(ip,narg,c);
581158766Snetchild				(void)putchar(',');
582158766Snetchild				whencename ((int)*ip);
583158766Snetchild				ip++;
584158766Snetchild				narg--;
585171221Speter#endif
586171221Speter			} else if (ktr->ktr_code == SYS_lseek) {
587171221Speter				print_number(ip,narg,c);
588171221Speter				/* Hidden 'pad' argument, not in lseek(2) */
589171221Speter				print_number(ip,narg,c);
590171221Speter				(void)putchar(',');
591171221Speter				whencename ((int)*ip);
592171221Speter				ip++;
593171221Speter				narg--;
594171221Speter
595158766Snetchild			} else if (ktr->ktr_code == SYS_flock) {
596158766Snetchild				print_number(ip,narg,c);
597158766Snetchild				(void)putchar(',');
598158766Snetchild				flockname((int)*ip);
599158766Snetchild				ip++;
600158766Snetchild				narg--;
601158766Snetchild			} else if (ktr->ktr_code == SYS_mkfifo ||
602158766Snetchild				   ktr->ktr_code == SYS_mkdir) {
603158766Snetchild				print_number(ip,narg,c);
604158766Snetchild				(void)putchar(',');
605158766Snetchild				modename((int)*ip);
606158766Snetchild				ip++;
607158766Snetchild				narg--;
608158766Snetchild			} else if (ktr->ktr_code == SYS_shutdown) {
609158766Snetchild				print_number(ip,narg,c);
610158766Snetchild				(void)putchar(',');
611158766Snetchild				shutdownhowname((int)*ip);
612158766Snetchild				ip++;
613158766Snetchild				narg--;
614158766Snetchild			} else if (ktr->ktr_code == SYS_socketpair) {
615158766Snetchild				(void)putchar('(');
616158766Snetchild				sockdomainname((int)*ip);
617158766Snetchild				ip++;
618158766Snetchild				narg--;
619158766Snetchild				(void)putchar(',');
620158766Snetchild				socktypename((int)*ip);
621158766Snetchild				ip++;
622158766Snetchild				narg--;
623158766Snetchild				c = ',';
624158766Snetchild			} else if (ktr->ktr_code == SYS_getrlimit ||
625158766Snetchild				   ktr->ktr_code == SYS_setrlimit) {
626158766Snetchild				(void)putchar('(');
627158766Snetchild				rlimitname((int)*ip);
628158766Snetchild				ip++;
629158766Snetchild				narg--;
630158766Snetchild				c = ',';
631158766Snetchild			} else if (ktr->ktr_code == SYS_quotactl) {
632158766Snetchild				print_number(ip,narg,c);
633174346Sjhb				(void)putchar(',');
634158766Snetchild				quotactlname((int)*ip);
635158766Snetchild				ip++;
636158766Snetchild				narg--;
637158766Snetchild				c = ',';
638158766Snetchild			} else if (ktr->ktr_code == SYS_nfssvc) {
639158766Snetchild				(void)putchar('(');
640158766Snetchild				nfssvcname((int)*ip);
641158766Snetchild				ip++;
642158766Snetchild				narg--;
643158766Snetchild				c = ',';
644158766Snetchild			} else if (ktr->ktr_code == SYS_rtprio) {
645158766Snetchild				(void)putchar('(');
646158766Snetchild				rtprioname((int)*ip);
647158766Snetchild				ip++;
648158766Snetchild				narg--;
649158766Snetchild				c = ',';
650158766Snetchild			} else if (ktr->ktr_code == SYS___semctl) {
651158766Snetchild				print_number(ip,narg,c);
652158766Snetchild				print_number(ip,narg,c);
653174346Sjhb				(void)putchar(',');
654158766Snetchild				semctlname((int)*ip);
655158766Snetchild				ip++;
656158766Snetchild				narg--;
657158766Snetchild			} else if (ktr->ktr_code == SYS_semget) {
658158766Snetchild				print_number(ip,narg,c);
659158766Snetchild				print_number(ip,narg,c);
660174346Sjhb				(void)putchar(',');
661158766Snetchild				semgetname((int)*ip);
662158766Snetchild				ip++;
663158766Snetchild				narg--;
664158766Snetchild			} else if (ktr->ktr_code == SYS_msgctl) {
665158766Snetchild				print_number(ip,narg,c);
666174346Sjhb				(void)putchar(',');
667158766Snetchild				shmctlname((int)*ip);
668158766Snetchild				ip++;
669158766Snetchild				narg--;
670158766Snetchild			} else if (ktr->ktr_code == SYS_shmat) {
671158766Snetchild				print_number(ip,narg,c);
672158766Snetchild				print_number(ip,narg,c);
673174346Sjhb				(void)putchar(',');
674158766Snetchild				shmatname((int)*ip);
675158766Snetchild				ip++;
676158766Snetchild				narg--;
677158766Snetchild			} else if (ktr->ktr_code == SYS_shmctl) {
678158766Snetchild				print_number(ip,narg,c);
679174346Sjhb				(void)putchar(',');
680158766Snetchild				shmctlname((int)*ip);
681158766Snetchild				ip++;
682158766Snetchild				narg--;
683158766Snetchild			} else if (ktr->ktr_code == SYS_minherit) {
684158766Snetchild				print_number(ip,narg,c);
685158766Snetchild				print_number(ip,narg,c);
686174346Sjhb				(void)putchar(',');
687158766Snetchild				minheritname((int)*ip);
688158766Snetchild				ip++;
689158766Snetchild				narg--;
690158766Snetchild			} else if (ktr->ktr_code == SYS_rfork) {
691158766Snetchild				(void)putchar('(');
692158766Snetchild				rforkname((int)*ip);
693158766Snetchild				ip++;
694158766Snetchild				narg--;
695158766Snetchild				c = ',';
696158766Snetchild			} else if (ktr->ktr_code == SYS_lio_listio) {
697158766Snetchild				(void)putchar('(');
698158766Snetchild				lio_listioname((int)*ip);
699158766Snetchild				ip++;
700158766Snetchild				narg--;
701158766Snetchild				c = ',';
702158766Snetchild			} else if (ktr->ktr_code == SYS_mlockall) {
703158766Snetchild				(void)putchar('(');
704158766Snetchild				mlockallname((int)*ip);
705158766Snetchild				ip++;
706158766Snetchild				narg--;
707158766Snetchild			} else if (ktr->ktr_code == SYS_sched_setscheduler) {
708158766Snetchild				print_number(ip,narg,c);
709174346Sjhb				(void)putchar(',');
710158766Snetchild				schedpolicyname((int)*ip);
711158766Snetchild				ip++;
712158766Snetchild				narg--;
713158766Snetchild			} else if (ktr->ktr_code == SYS_sched_get_priority_max ||
714158766Snetchild				   ktr->ktr_code == SYS_sched_get_priority_min) {
715158766Snetchild				(void)putchar('(');
716158766Snetchild				schedpolicyname((int)*ip);
717158766Snetchild				ip++;
718158766Snetchild				narg--;
719158766Snetchild			} else if (ktr->ktr_code == SYS_sendfile) {
720158766Snetchild				print_number(ip,narg,c);
721158766Snetchild				print_number(ip,narg,c);
722158766Snetchild				print_number(ip,narg,c);
723158766Snetchild				print_number(ip,narg,c);
724158766Snetchild				print_number(ip,narg,c);
725158766Snetchild				print_number(ip,narg,c);
726174346Sjhb				(void)putchar(',');
727158766Snetchild				sendfileflagsname((int)*ip);
728158766Snetchild				ip++;
729158766Snetchild				narg--;
730158766Snetchild			} else if (ktr->ktr_code == SYS_kldsym) {
731158766Snetchild				print_number(ip,narg,c);
732174346Sjhb				(void)putchar(',');
733158766Snetchild				kldsymcmdname((int)*ip);
734158766Snetchild				ip++;
735158766Snetchild				narg--;
736158766Snetchild			} else if (ktr->ktr_code == SYS_sigprocmask) {
737158766Snetchild				(void)putchar('(');
738158766Snetchild				sigprocmaskhowname((int)*ip);
739158766Snetchild				ip++;
740158766Snetchild				narg--;
741158766Snetchild				c = ',';
742158766Snetchild			} else if (ktr->ktr_code == SYS___acl_get_file ||
743158766Snetchild				   ktr->ktr_code == SYS___acl_set_file ||
744158766Snetchild				   ktr->ktr_code == SYS___acl_get_fd ||
745158766Snetchild				   ktr->ktr_code == SYS___acl_set_fd ||
746158766Snetchild				   ktr->ktr_code == SYS___acl_delete_file ||
747158766Snetchild				   ktr->ktr_code == SYS___acl_delete_fd ||
748158766Snetchild				   ktr->ktr_code == SYS___acl_aclcheck_file ||
749158766Snetchild				   ktr->ktr_code == SYS___acl_aclcheck_fd ||
750158766Snetchild				   ktr->ktr_code == SYS___acl_get_link ||
751158766Snetchild				   ktr->ktr_code == SYS___acl_set_link ||
752158766Snetchild				   ktr->ktr_code == SYS___acl_delete_link ||
753158766Snetchild				   ktr->ktr_code == SYS___acl_aclcheck_link) {
754158766Snetchild				print_number(ip,narg,c);
755174346Sjhb				(void)putchar(',');
756158766Snetchild				acltypename((int)*ip);
757158766Snetchild				ip++;
758158766Snetchild				narg--;
759158766Snetchild			} else if (ktr->ktr_code == SYS_sigaction) {
760158766Snetchild				(void)putchar('(');
761158766Snetchild				signame((int)*ip);
762158766Snetchild				ip++;
763158766Snetchild				narg--;
764158766Snetchild				c = ',';
765158766Snetchild			} else if (ktr->ktr_code == SYS_extattrctl) {
766158766Snetchild				print_number(ip,narg,c);
767174346Sjhb				(void)putchar(',');
768158766Snetchild				extattrctlname((int)*ip);
769158766Snetchild				ip++;
770158766Snetchild				narg--;
771158766Snetchild			} else if (ktr->ktr_code == SYS_nmount) {
772158766Snetchild				print_number(ip,narg,c);
773158766Snetchild				print_number(ip,narg,c);
774158766Snetchild				(void)putchar(',');
775158766Snetchild				mountflagsname ((int)*ip);
776158766Snetchild				ip++;
777158766Snetchild				narg--;
778158766Snetchild			} else if (ktr->ktr_code == SYS_thr_create) {
779158766Snetchild				print_number(ip,narg,c);
780158766Snetchild				print_number(ip,narg,c);
781158766Snetchild				(void)putchar(',');
782158766Snetchild				thrcreateflagsname ((int)*ip);
783158766Snetchild				ip++;
784158766Snetchild				narg--;
785158766Snetchild			} else if (ktr->ktr_code == SYS_thr_kill) {
786158766Snetchild				print_number(ip,narg,c);
787158766Snetchild				(void)putchar(',');
788158766Snetchild				signame ((int)*ip);
789158766Snetchild				ip++;
790158766Snetchild				narg--;
791158766Snetchild			} else if (ktr->ktr_code == SYS_kldunloadf) {
792158766Snetchild				print_number(ip,narg,c);
793158766Snetchild				(void)putchar(',');
794158766Snetchild				kldunloadfflagsname ((int)*ip);
795158766Snetchild				ip++;
796158766Snetchild				narg--;
7971590Srgrimes			}
7981590Srgrimes		}
7991590Srgrimes		while (narg) {
800158766Snetchild			print_number(ip,narg,c);
8011590Srgrimes		}
8021590Srgrimes		(void)putchar(')');
8031590Srgrimes	}
8041590Srgrimes	(void)putchar('\n');
8051590Srgrimes}
8061590Srgrimes
807100824Sdwmalonevoid
808100824Sdwmalonektrsysret(struct ktr_sysret *ktr)
8091590Srgrimes{
810100824Sdwmalone	register_t ret = ktr->ktr_retval;
811100824Sdwmalone	int error = ktr->ktr_error;
812100824Sdwmalone	int code = ktr->ktr_code;
8131590Srgrimes
8141590Srgrimes	if (code >= nsyscalls || code < 0)
8151590Srgrimes		(void)printf("[%d] ", code);
8161590Srgrimes	else
8171590Srgrimes		(void)printf("%s ", syscallnames[code]);
8181590Srgrimes
8191590Srgrimes	if (error == 0) {
8201590Srgrimes		if (fancy) {
8211590Srgrimes			(void)printf("%d", ret);
8221590Srgrimes			if (ret < 0 || ret > 9)
82347957Sdt				(void)printf("/%#lx", (long)ret);
8241590Srgrimes		} else {
8251590Srgrimes			if (decimal)
82647957Sdt				(void)printf("%ld", (long)ret);
8271590Srgrimes			else
82847957Sdt				(void)printf("%#lx", (long)ret);
8291590Srgrimes		}
8301590Srgrimes	} else if (error == ERESTART)
8311590Srgrimes		(void)printf("RESTART");
8321590Srgrimes	else if (error == EJUSTRETURN)
8331590Srgrimes		(void)printf("JUSTRETURN");
8341590Srgrimes	else {
8351590Srgrimes		(void)printf("-1 errno %d", ktr->ktr_error);
8361590Srgrimes		if (fancy)
8371590Srgrimes			(void)printf(" %s", strerror(ktr->ktr_error));
8381590Srgrimes	}
8391590Srgrimes	(void)putchar('\n');
8401590Srgrimes}
8411590Srgrimes
842100824Sdwmalonevoid
843100824Sdwmalonektrnamei(char *cp, int len)
8441590Srgrimes{
8451590Srgrimes	(void)printf("\"%.*s\"\n", len, cp);
8461590Srgrimes}
8471590Srgrimes
848100824Sdwmalonevoid
849115759Speterhexdump(char *p, int len, int screenwidth)
8501590Srgrimes{
851115759Speter	int n, i;
852115759Speter	int width;
853115759Speter
854115759Speter	width = 0;
855115759Speter	do {
856115759Speter		width += 2;
857115759Speter		i = 13;			/* base offset */
858115759Speter		i += (width / 2) + 1;	/* spaces every second byte */
859115759Speter		i += (width * 2);	/* width of bytes */
860115759Speter		i += 3;			/* "  |" */
861115759Speter		i += width;		/* each byte */
862115759Speter		i += 1;			/* "|" */
863115759Speter	} while (i < screenwidth);
864115759Speter	width -= 2;
865115759Speter
866115759Speter	for (n = 0; n < len; n += width) {
867115759Speter		for (i = n; i < n + width; i++) {
868115759Speter			if ((i % width) == 0) {	/* beginning of line */
869115759Speter				printf("       0x%04x", i);
870115759Speter			}
871115759Speter			if ((i % 2) == 0) {
872115759Speter				printf(" ");
873115759Speter			}
874115759Speter			if (i < len)
875115759Speter				printf("%02x", p[i] & 0xff);
876115759Speter			else
877115759Speter				printf("  ");
878115759Speter		}
879115759Speter		printf("  |");
880115759Speter		for (i = n; i < n + width; i++) {
881115759Speter			if (i >= len)
882115759Speter				break;
883115759Speter			if (p[i] >= ' ' && p[i] <= '~')
884115759Speter				printf("%c", p[i]);
885115759Speter			else
886115759Speter				printf(".");
887115759Speter		}
888115759Speter		printf("|\n");
889115759Speter	}
890115759Speter	if ((i % width) != 0)
891115759Speter		printf("\n");
892115759Speter}
893115759Speter
894115759Spetervoid
895115759Spetervisdump(char *dp, int datalen, int screenwidth)
896115759Speter{
897115759Speter	int col = 0;
898100824Sdwmalone	char *cp;
899100824Sdwmalone	int width;
9001590Srgrimes	char visbuf[5];
9011590Srgrimes
9021590Srgrimes	(void)printf("       \"");
9031590Srgrimes	col = 8;
9041590Srgrimes	for (;datalen > 0; datalen--, dp++) {
9051590Srgrimes		(void) vis(visbuf, *dp, VIS_CSTYLE, *(dp+1));
9061590Srgrimes		cp = visbuf;
9071590Srgrimes		/*
9081590Srgrimes		 * Keep track of printables and
9091590Srgrimes		 * space chars (like fold(1)).
9101590Srgrimes		 */
9111590Srgrimes		if (col == 0) {
9121590Srgrimes			(void)putchar('\t');
9131590Srgrimes			col = 8;
9141590Srgrimes		}
9151590Srgrimes		switch(*cp) {
9161590Srgrimes		case '\n':
9171590Srgrimes			col = 0;
9181590Srgrimes			(void)putchar('\n');
9191590Srgrimes			continue;
9201590Srgrimes		case '\t':
9211590Srgrimes			width = 8 - (col&07);
9221590Srgrimes			break;
9231590Srgrimes		default:
9241590Srgrimes			width = strlen(cp);
9251590Srgrimes		}
9261590Srgrimes		if (col + width > (screenwidth-2)) {
9271590Srgrimes			(void)printf("\\\n\t");
9281590Srgrimes			col = 8;
9291590Srgrimes		}
9301590Srgrimes		col += width;
9311590Srgrimes		do {
9321590Srgrimes			(void)putchar(*cp++);
9331590Srgrimes		} while (*cp);
9341590Srgrimes	}
9351590Srgrimes	if (col == 0)
9361590Srgrimes		(void)printf("       ");
9371590Srgrimes	(void)printf("\"\n");
9381590Srgrimes}
9391590Srgrimes
940115759Spetervoid
941115759Speterktrgenio(struct ktr_genio *ktr, int len)
942115759Speter{
943115759Speter	int datalen = len - sizeof (struct ktr_genio);
944115759Speter	char *dp = (char *)ktr + sizeof (struct ktr_genio);
945115759Speter	static int screenwidth = 0;
946115759Speter	int i, binary;
947115759Speter
948115759Speter	if (screenwidth == 0) {
949115759Speter		struct winsize ws;
950115759Speter
951115759Speter		if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 &&
952115759Speter		    ws.ws_col > 8)
953115759Speter			screenwidth = ws.ws_col;
954115759Speter		else
955115759Speter			screenwidth = 80;
956115759Speter	}
957115759Speter	printf("fd %d %s %d byte%s\n", ktr->ktr_fd,
958115759Speter		ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen,
959115759Speter		datalen == 1 ? "" : "s");
960152331Srwatson	if (suppressdata)
961152331Srwatson		return;
962115759Speter	if (maxdata && datalen > maxdata)
963115759Speter		datalen = maxdata;
964115759Speter
965115759Speter	for (i = 0, binary = 0; i < datalen && binary == 0; i++)  {
966115759Speter		if (dp[i] >= 32 && dp[i] < 127)
967115759Speter			continue;
968115759Speter		if (dp[i] == 10 || dp[i] == 13 || dp[i] == 0 || dp[i] == 9)
969115759Speter			continue;
970115759Speter		binary = 1;
971115759Speter	}
972115759Speter	if (binary)
973115759Speter		hexdump(dp, datalen, screenwidth);
974115759Speter	else
975115759Speter		visdump(dp, datalen, screenwidth);
976115759Speter}
977115759Speter
978100824Sdwmaloneconst char *signames[] = {
9791590Srgrimes	"NULL", "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT",	/*  1 - 6  */
9801590Srgrimes	"EMT", "FPE", "KILL", "BUS", "SEGV", "SYS",		/*  7 - 12 */
9811590Srgrimes	"PIPE", "ALRM",  "TERM", "URG", "STOP", "TSTP",		/* 13 - 18 */
9821590Srgrimes	"CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU",		/* 19 - 24 */
9831590Srgrimes	"XFSZ", "VTALRM", "PROF", "WINCH", "29", "USR1",	/* 25 - 30 */
9841590Srgrimes	"USR2", NULL,						/* 31 - 32 */
9851590Srgrimes};
9861590Srgrimes
987100824Sdwmalonevoid
988100824Sdwmalonektrpsig(struct ktr_psig *psig)
9891590Srgrimes{
990160294Skib	if (psig->signo > 0 && psig->signo < NSIG)
991160296Smaxim		(void)printf("SIG%s ", signames[psig->signo]);
992160294Skib	else
993160296Smaxim		(void)printf("SIG %d ", psig->signo);
9941590Srgrimes	if (psig->action == SIG_DFL)
9951590Srgrimes		(void)printf("SIG_DFL\n");
996100824Sdwmalone	else {
99747957Sdt		(void)printf("caught handler=0x%lx mask=0x%x code=0x%x\n",
998100824Sdwmalone		    (u_long)psig->action, psig->mask.__bits[0], psig->code);
999100824Sdwmalone	}
10001590Srgrimes}
10011590Srgrimes
1002100824Sdwmalonevoid
1003100824Sdwmalonektrcsw(struct ktr_csw *cs)
10041590Srgrimes{
10051590Srgrimes	(void)printf("%s %s\n", cs->out ? "stop" : "resume",
10061590Srgrimes		cs->user ? "user" : "kernel");
10071590Srgrimes}
10081590Srgrimes
1009165916Sjhb#define	UTRACE_DLOPEN_START		1
1010165916Sjhb#define	UTRACE_DLOPEN_STOP		2
1011165916Sjhb#define	UTRACE_DLCLOSE_START		3
1012165916Sjhb#define	UTRACE_DLCLOSE_STOP		4
1013165916Sjhb#define	UTRACE_LOAD_OBJECT		5
1014165916Sjhb#define	UTRACE_UNLOAD_OBJECT		6
1015165916Sjhb#define	UTRACE_ADD_RUNDEP		7
1016165916Sjhb#define	UTRACE_PRELOAD_FINISHED		8
1017165916Sjhb#define	UTRACE_INIT_CALL		9
1018165916Sjhb#define	UTRACE_FINI_CALL		10
1019165916Sjhb
1020165916Sjhbstruct utrace_rtld {
1021165916Sjhb	char sig[4];				/* 'RTLD' */
1022165916Sjhb	int event;
1023165916Sjhb	void *handle;
1024165916Sjhb	void *mapbase;
1025165916Sjhb	size_t mapsize;
1026165916Sjhb	int refcnt;
1027165916Sjhb	char name[MAXPATHLEN];
1028165916Sjhb};
1029165916Sjhb
1030165916Sjhbvoid
1031165916Sjhbktruser_rtld(int len, unsigned char *p)
1032165916Sjhb{
1033165916Sjhb	struct utrace_rtld *ut = (struct utrace_rtld *)p;
1034165916Sjhb	void *parent;
1035165916Sjhb	int mode;
1036165916Sjhb
1037165916Sjhb	switch (ut->event) {
1038165916Sjhb	case UTRACE_DLOPEN_START:
1039165916Sjhb		mode = ut->refcnt;
1040165916Sjhb		printf("dlopen(%s, ", ut->name);
1041165916Sjhb		switch (mode & RTLD_MODEMASK) {
1042165916Sjhb		case RTLD_NOW:
1043165916Sjhb			printf("RTLD_NOW");
1044165916Sjhb			break;
1045165916Sjhb		case RTLD_LAZY:
1046165916Sjhb			printf("RTLD_LAZY");
1047165916Sjhb			break;
1048165916Sjhb		default:
1049165916Sjhb			printf("%#x", mode & RTLD_MODEMASK);
1050165916Sjhb		}
1051165916Sjhb		if (mode & RTLD_GLOBAL)
1052165916Sjhb			printf(" | RTLD_GLOBAL");
1053165916Sjhb		if (mode & RTLD_TRACE)
1054165916Sjhb			printf(" | RTLD_TRACE");
1055165916Sjhb		if (mode & ~(RTLD_MODEMASK | RTLD_GLOBAL | RTLD_TRACE))
1056165916Sjhb			printf(" | %#x", mode &
1057165916Sjhb			    ~(RTLD_MODEMASK | RTLD_GLOBAL | RTLD_TRACE));
1058165916Sjhb		printf(")\n");
1059165916Sjhb		break;
1060165916Sjhb	case UTRACE_DLOPEN_STOP:
1061165916Sjhb		printf("%p = dlopen(%s) ref %d\n", ut->handle, ut->name,
1062165916Sjhb		    ut->refcnt);
1063165916Sjhb		break;
1064165916Sjhb	case UTRACE_DLCLOSE_START:
1065165916Sjhb		printf("dlclose(%p) (%s, %d)\n", ut->handle, ut->name,
1066165916Sjhb		    ut->refcnt);
1067165916Sjhb		break;
1068165916Sjhb	case UTRACE_DLCLOSE_STOP:
1069165916Sjhb		printf("dlclose(%p) finished\n", ut->handle);
1070165916Sjhb		break;
1071165916Sjhb	case UTRACE_LOAD_OBJECT:
1072165916Sjhb		printf("RTLD: loaded   %p @ %p - %p (%s)\n", ut->handle,
1073165916Sjhb		    ut->mapbase, (char *)ut->mapbase + ut->mapsize - 1,
1074165916Sjhb		    ut->name);
1075165916Sjhb		break;
1076165916Sjhb	case UTRACE_UNLOAD_OBJECT:
1077165916Sjhb		printf("RTLD: unloaded %p @ %p - %p (%s)\n", ut->handle,
1078165916Sjhb		    ut->mapbase, (char *)ut->mapbase + ut->mapsize - 1,
1079165916Sjhb		    ut->name);
1080165916Sjhb		break;
1081165916Sjhb	case UTRACE_ADD_RUNDEP:
1082165916Sjhb		parent = ut->mapbase;
1083165916Sjhb		printf("RTLD: %p now depends on %p (%s, %d)\n", parent,
1084165916Sjhb		    ut->handle, ut->name, ut->refcnt);
1085165916Sjhb		break;
1086165916Sjhb	case UTRACE_PRELOAD_FINISHED:
1087165916Sjhb		printf("RTLD: LD_PRELOAD finished\n");
1088165916Sjhb		break;
1089165916Sjhb	case UTRACE_INIT_CALL:
1090165916Sjhb		printf("RTLD: init %p for %p (%s)\n", ut->mapbase, ut->handle,
1091165916Sjhb		    ut->name);
1092165916Sjhb		break;
1093165916Sjhb	case UTRACE_FINI_CALL:
1094165916Sjhb		printf("RTLD: fini %p for %p (%s)\n", ut->mapbase, ut->handle,
1095165916Sjhb		    ut->name);
1096165916Sjhb		break;
1097165916Sjhb	default:
1098165916Sjhb		p += 4;
1099165916Sjhb		len -= 4;
1100165916Sjhb		printf("RTLD: %d ", len);
1101165916Sjhb		while (len--)
1102165916Sjhb			if (decimal)
1103165916Sjhb				printf(" %d", *p++);
1104165916Sjhb			else
1105165916Sjhb				printf(" %02x", *p++);
1106165916Sjhb		printf("\n");
1107165916Sjhb	}
1108165916Sjhb}
1109165916Sjhb
1110165812Sjhbstruct utrace_malloc {
1111165812Sjhb	void *p;
1112165812Sjhb	size_t s;
1113165812Sjhb	void *r;
1114165812Sjhb};
1115165812Sjhb
1116100824Sdwmalonevoid
1117165812Sjhbktruser_malloc(int len, unsigned char *p)
1118165812Sjhb{
1119165812Sjhb	struct utrace_malloc *ut = (struct utrace_malloc *)p;
1120165812Sjhb
1121165812Sjhb	if (ut->p == NULL) {
1122165812Sjhb		if (ut->s == 0 && ut->r == NULL)
1123165812Sjhb			printf("malloc_init()\n");
1124165812Sjhb		else
1125165812Sjhb			printf("%p = malloc(%zu)\n", ut->r, ut->s);
1126165812Sjhb	} else {
1127165812Sjhb		if (ut->s == 0)
1128165812Sjhb			printf("free(%p)\n", ut->p);
1129165812Sjhb		else
1130165812Sjhb			printf("%p = realloc(%p, %zu)\n", ut->r, ut->p, ut->s);
1131165812Sjhb	}
1132165812Sjhb}
1133165812Sjhb
1134165812Sjhbvoid
1135100824Sdwmalonektruser(int len, unsigned char *p)
113618400Sphk{
1137165812Sjhb
1138165916Sjhb	if (len >= 8 && bcmp(p, "RTLD", 4) == 0) {
1139165916Sjhb		ktruser_rtld(len, p);
1140165916Sjhb		return;
1141165916Sjhb	}
1142165916Sjhb
1143165812Sjhb	if (len == sizeof(struct utrace_malloc)) {
1144165812Sjhb		ktruser_malloc(len, p);
1145165812Sjhb		return;
1146165812Sjhb	}
1147165812Sjhb
114818470Sphk	(void)printf("%d ", len);
114918470Sphk	while (len--)
1150127402Sphk		if (decimal)
1151127402Sphk			(void)printf(" %d", *p++);
1152127402Sphk		else
1153127402Sphk			(void)printf(" %02x", *p++);
115418400Sphk	(void)printf("\n");
115518400Sphk}
115618400Sphk
1157100824Sdwmalonevoid
1158176471Sdesktrsockaddr(struct sockaddr *sa)
1159176471Sdes{
1160176471Sdes/*
1161176471Sdes TODO: Support additional address families
1162176471Sdes	#include <netnatm/natm.h>
1163176471Sdes	struct sockaddr_natm	*natm;
1164176471Sdes	#include <netsmb/netbios.h>
1165176471Sdes	struct sockaddr_nb	*nb;
1166176471Sdes*/
1167176471Sdes	char addr[64];
1168176471Sdes
1169176471Sdes	/*
1170176471Sdes	 * note: ktrstruct() has already verified that sa points to a
1171176471Sdes	 * buffer at least sizeof(struct sockaddr) bytes long and exactly
1172176471Sdes	 * sa->sa_len bytes long.
1173176471Sdes	 */
1174176471Sdes	printf("struct sockaddr { ");
1175176471Sdes	sockfamilyname(sa->sa_family);
1176176471Sdes	printf(", ");
1177176471Sdes
1178176471Sdes#define check_sockaddr_len(n)					\
1179176471Sdes	if (sa_##n->s##n##_len < sizeof(struct sockaddr_##n)) {	\
1180176471Sdes		printf("invalid");				\
1181176471Sdes		break;						\
1182176471Sdes	}
1183176471Sdes
1184176471Sdes	switch(sa->sa_family) {
1185176471Sdes	case AF_INET: {
1186176471Sdes		struct sockaddr_in	*sa_in;
1187176471Sdes
1188176471Sdes		sa_in = (struct sockaddr_in *)sa;
1189176471Sdes		check_sockaddr_len(in);
1190176471Sdes		inet_ntop(AF_INET, &sa_in->sin_addr, addr, sizeof addr);
1191176471Sdes		printf("%s:%u", addr, ntohs(sa_in->sin_port));
1192176471Sdes		break;
1193176471Sdes	}
1194176471Sdes#ifdef NETATALK
1195176471Sdes	case AF_APPLETALK: {
1196176471Sdes		struct sockaddr_at	*sa_at;
1197176471Sdes		struct netrange		*nr;
1198176471Sdes
1199176471Sdes		sa_at = (struct sockaddr_at *)sa;
1200176471Sdes		check_sockaddr_len(at);
1201176471Sdes		nr = &sa_at->sat_range.r_netrange;
1202176471Sdes		printf("%d.%d, %d-%d, %d", ntohs(sa_at->sat_addr.s_net),
1203176471Sdes			sa_at->sat_addr.s_node, ntohs(nr->nr_firstnet),
1204176471Sdes			ntohs(nr->nr_lastnet), nr->nr_phase);
1205176471Sdes		break;
1206176471Sdes	}
1207176471Sdes#endif
1208176471Sdes	case AF_INET6: {
1209176471Sdes		struct sockaddr_in6	*sa_in6;
1210176471Sdes
1211176471Sdes		sa_in6 = (struct sockaddr_in6 *)sa;
1212176471Sdes		check_sockaddr_len(in6);
1213176471Sdes		inet_ntop(AF_INET6, &sa_in6->sin6_addr, addr, sizeof addr);
1214176471Sdes		printf("[%s]:%u", addr, htons(sa_in6->sin6_port));
1215176471Sdes		break;
1216176471Sdes	}
1217176471Sdes#ifdef IPX
1218176471Sdes	case AF_IPX: {
1219176471Sdes		struct sockaddr_ipx	*sa_ipx;
1220176471Sdes
1221176471Sdes		sa_ipx = (struct sockaddr_ipx *)sa;
1222176471Sdes		check_sockaddr_len(ipx);
1223176471Sdes		/* XXX wish we had ipx_ntop */
1224176471Sdes		printf("%s", ipx_ntoa(sa_ipx->sipx_addr));
1225176471Sdes		break;
1226176471Sdes	}
1227176471Sdes#endif
1228176471Sdes	case AF_UNIX: {
1229176471Sdes		struct sockaddr_un *sa_un;
1230176471Sdes
1231176471Sdes		sa_un = (struct sockaddr_un *)sa;
1232176471Sdes		check_sockaddr_len(un);
1233176471Sdes		printf("%.*s", (int)sizeof(sa_un->sun_path), sa_un->sun_path);
1234176471Sdes		break;
1235176471Sdes	}
1236176471Sdes	default:
1237176471Sdes		printf("unknown address family");
1238176471Sdes	}
1239176471Sdes	printf(" }\n");
1240176471Sdes}
1241176471Sdes
1242176471Sdesvoid
1243176471Sdesktrstat(struct stat *statp)
1244176471Sdes{
1245176471Sdes	char mode[12], timestr[PATH_MAX + 4];
1246176471Sdes	struct passwd *pwd;
1247176471Sdes	struct group  *grp;
1248176471Sdes	struct tm *tm;
1249176471Sdes
1250176471Sdes	/*
1251176471Sdes	 * note: ktrstruct() has already verified that statp points to a
1252176471Sdes	 * buffer exactly sizeof(struct stat) bytes long.
1253176471Sdes	 */
1254176471Sdes	printf("struct stat {");
1255176471Sdes	strmode(statp->st_mode, mode);
1256176471Sdes	printf("dev=%ju, ino=%ju, mode=%s, nlink=%ju, ",
1257176471Sdes		(uintmax_t)statp->st_dev, (uintmax_t)statp->st_ino, mode,
1258176471Sdes		(uintmax_t)statp->st_nlink);
1259176471Sdes	if (resolv == 0 || (pwd = getpwuid(statp->st_uid)) == NULL)
1260176471Sdes		printf("uid=%ju, ", (uintmax_t)statp->st_uid);
1261176471Sdes	else
1262176471Sdes		printf("uid=\"%s\", ", pwd->pw_name);
1263176471Sdes	if (resolv == 0 || (grp = getgrgid(statp->st_gid)) == NULL)
1264176471Sdes		printf("gid=%ju, ", (uintmax_t)statp->st_gid);
1265176471Sdes	else
1266176471Sdes		printf("gid=\"%s\", ", grp->gr_name);
1267176471Sdes	printf("rdev=%ju, ", (uintmax_t)statp->st_rdev);
1268176471Sdes	printf("atime=");
1269176471Sdes	if (resolv == 0)
1270176471Sdes		printf("%ld", statp->st_atimespec.tv_sec);
1271176471Sdes	else {
1272176471Sdes		tm = localtime(&statp->st_atimespec.tv_sec);
1273176471Sdes		(void)strftime(timestr, sizeof(timestr), TIME_FORMAT, tm);
1274176471Sdes		printf("\"%s\"", timestr);
1275176471Sdes	}
1276176471Sdes	if (statp->st_atimespec.tv_nsec != 0)
1277176471Sdes		printf(".%09ld, ", statp->st_atimespec.tv_nsec);
1278176471Sdes	else
1279176471Sdes		printf(", ");
1280176471Sdes	printf("stime=");
1281176471Sdes	if (resolv == 0)
1282176471Sdes		printf("%ld", statp->st_mtimespec.tv_sec);
1283176471Sdes	else {
1284176471Sdes		tm = localtime(&statp->st_mtimespec.tv_sec);
1285176471Sdes		(void)strftime(timestr, sizeof(timestr), TIME_FORMAT, tm);
1286176471Sdes		printf("\"%s\"", timestr);
1287176471Sdes	}
1288176471Sdes	if (statp->st_mtimespec.tv_nsec != 0)
1289176471Sdes		printf(".%09ld, ", statp->st_mtimespec.tv_nsec);
1290176471Sdes	else
1291176471Sdes		printf(", ");
1292176471Sdes	printf("ctime=");
1293176471Sdes	if (resolv == 0)
1294176471Sdes		printf("%ld", statp->st_ctimespec.tv_sec);
1295176471Sdes	else {
1296176471Sdes		tm = localtime(&statp->st_ctimespec.tv_sec);
1297176471Sdes		(void)strftime(timestr, sizeof(timestr), TIME_FORMAT, tm);
1298176471Sdes		printf("\"%s\"", timestr);
1299176471Sdes	}
1300176471Sdes	if (statp->st_ctimespec.tv_nsec != 0)
1301176471Sdes		printf(".%09ld, ", statp->st_ctimespec.tv_nsec);
1302176471Sdes	else
1303176471Sdes		printf(", ");
1304176471Sdes	printf("birthtime=");
1305176471Sdes	if (resolv == 0)
1306176471Sdes		printf("%ld", statp->st_birthtimespec.tv_sec);
1307176471Sdes	else {
1308176471Sdes		tm = localtime(&statp->st_birthtimespec.tv_sec);
1309176471Sdes		(void)strftime(timestr, sizeof(timestr), TIME_FORMAT, tm);
1310176471Sdes		printf("\"%s\"", timestr);
1311176471Sdes	}
1312176471Sdes	if (statp->st_birthtimespec.tv_nsec != 0)
1313176471Sdes		printf(".%09ld, ", statp->st_birthtimespec.tv_nsec);
1314176471Sdes	else
1315176471Sdes		printf(", ");
1316176471Sdes	printf("size=%jd, blksize=%ju, blocks=%jd, flags=0x%x",
1317176471Sdes		(uintmax_t)statp->st_size, (uintmax_t)statp->st_blksize,
1318176471Sdes		(intmax_t)statp->st_blocks, statp->st_flags);
1319176471Sdes	printf(" }\n");
1320176471Sdes}
1321176471Sdes
1322176471Sdesvoid
1323176471Sdesktrstruct(char *buf, size_t buflen)
1324176471Sdes{
1325176471Sdes	char *name, *data;
1326176471Sdes	size_t namelen, datalen;
1327176471Sdes	int i;
1328176471Sdes
1329176471Sdes	for (name = buf, namelen = 0;
1330176471Sdes	     namelen < buflen && name[namelen] != '\0';
1331176471Sdes	     ++namelen)
1332176471Sdes		/* nothing */;
1333176471Sdes	if (namelen == buflen)
1334176471Sdes		goto invalid;
1335176471Sdes	if (name[namelen] != '\0')
1336176471Sdes		goto invalid;
1337176471Sdes	data = buf + namelen + 1;
1338176471Sdes	datalen = buflen - namelen - 1;
1339176471Sdes	if (datalen == 0)
1340176471Sdes		goto invalid;
1341176471Sdes	/* sanity check */
1342176471Sdes	for (i = 0; i < namelen; ++i)
1343176471Sdes		if (!isalpha((unsigned char)name[i]))
1344176471Sdes			goto invalid;
1345176471Sdes	if (strcmp(name, "stat") == 0) {
1346176471Sdes		if (datalen != sizeof(struct stat))
1347176471Sdes			goto invalid;
1348176471Sdes		ktrstat((struct stat *)data);
1349176471Sdes	} else if (strcmp(name, "sockaddr") == 0) {
1350176471Sdes		if (datalen < sizeof(struct sockaddr) ||
1351176471Sdes		    datalen != ((struct sockaddr *)(data))->sa_len)
1352176471Sdes			goto invalid;
1353176471Sdes		ktrsockaddr((struct sockaddr *)data);
1354176471Sdes	} else {
1355176471Sdes		printf("unknown structure\n");
1356176471Sdes	}
1357176471Sdes	return;
1358176471Sdesinvalid:
1359176471Sdes	printf("invalid record\n");
1360176471Sdes}
1361176471Sdes
1362176471Sdesvoid
1363100824Sdwmaloneusage(void)
13641590Srgrimes{
1365176471Sdes	fprintf(stderr, "usage: kdump [-dEnlHRrsT] [-f trfile] "
1366177856Sru	    "[-m maxdata] [-p pid] [-t trstr]\n");
13671590Srgrimes	exit(1);
13681590Srgrimes}
1369