kdump.c revision 203551
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 203551 2010-02-06 16:01:38Z jh $");
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
70190168Sdelphij#include <arpa/inet.h>
71176471Sdes#include <netinet/in.h>
72190168Sdelphij#include <ctype.h>
73165916Sjhb#include <dlfcn.h>
7427443Scharnier#include <err.h>
75176471Sdes#include <grp.h>
76176471Sdes#include <inttypes.h>
7727443Scharnier#include <locale.h>
78176471Sdes#include <pwd.h>
791590Srgrimes#include <stdio.h>
801590Srgrimes#include <stdlib.h>
811590Srgrimes#include <string.h>
82176471Sdes#include <time.h>
8327443Scharnier#include <unistd.h>
8427443Scharnier#include <vis.h>
851590Srgrimes#include "ktrace.h"
86158766Snetchild#include "kdump_subr.h"
871590Srgrimes
88100824Sdwmaloneint fread_tail(void *, int, int);
89100824Sdwmalonevoid dumpheader(struct ktr_header *);
90100824Sdwmalonevoid ktrsyscall(struct ktr_syscall *);
91100824Sdwmalonevoid ktrsysret(struct ktr_sysret *);
92100824Sdwmalonevoid ktrnamei(char *, int);
93115759Spetervoid hexdump(char *, int, int);
94115759Spetervoid visdump(char *, int, int);
95100824Sdwmalonevoid ktrgenio(struct ktr_genio *, int);
96100824Sdwmalonevoid ktrpsig(struct ktr_psig *);
97100824Sdwmalonevoid ktrcsw(struct ktr_csw *);
98100824Sdwmalonevoid ktruser(int, unsigned char *);
99176471Sdesvoid ktrsockaddr(struct sockaddr *);
100176471Sdesvoid ktrstat(struct stat *);
101176471Sdesvoid ktrstruct(char *, size_t);
102100824Sdwmalonevoid usage(void);
103190168Sdelphijvoid sockfamilyname(int);
104135466Sruconst char *ioctlname(u_long);
105100824Sdwmalone
106176471Sdesint timestamp, decimal, fancy = 1, suppressdata, tail, threads, maxdata,
107176471Sdes    resolv = 0;
108100824Sdwmaloneconst char *tracefile = DEF_TRACEFILE;
1091590Srgrimesstruct ktr_header ktr_header;
1101590Srgrimes
111176471Sdes#define TIME_FORMAT	"%b %e %T %Y"
1121590Srgrimes#define eqs(s1, s2)	(strcmp((s1), (s2)) == 0)
1131590Srgrimes
114100824Sdwmaloneint
115100824Sdwmalonemain(int argc, char *argv[])
1161590Srgrimes{
1171590Srgrimes	int ch, ktrlen, size;
118100824Sdwmalone	void *m;
1191590Srgrimes	int trpoints = ALL_POINTS;
120112201Sjhb	int drop_logged;
121115759Speter	pid_t pid = 0;
1221590Srgrimes
12311823Sache	(void) setlocale(LC_CTYPE, "");
12411823Sache
125176471Sdes	while ((ch = getopt(argc,argv,"f:dElm:np:HRrsTt:")) != -1)
1261590Srgrimes		switch((char)ch) {
1271590Srgrimes		case 'f':
1281590Srgrimes			tracefile = optarg;
1291590Srgrimes			break;
1301590Srgrimes		case 'd':
1311590Srgrimes			decimal = 1;
1321590Srgrimes			break;
1331590Srgrimes		case 'l':
1341590Srgrimes			tail = 1;
1351590Srgrimes			break;
1361590Srgrimes		case 'm':
1371590Srgrimes			maxdata = atoi(optarg);
1381590Srgrimes			break;
1391590Srgrimes		case 'n':
1401590Srgrimes			fancy = 0;
1411590Srgrimes			break;
142115759Speter		case 'p':
143115759Speter			pid = atoi(optarg);
144115759Speter			break;
145176471Sdes		case 'r':
146176471Sdes			resolv = 1;
147176471Sdes			break;
148152331Srwatson		case 's':
149152331Srwatson			suppressdata = 1;
150152331Srwatson			break;
151123187Speter		case 'E':
152123187Speter			timestamp = 3;	/* elapsed timestamp */
153123187Speter			break;
154151930Srwatson		case 'H':
155151930Srwatson			threads = 1;
156151930Srwatson			break;
1571590Srgrimes		case 'R':
1581590Srgrimes			timestamp = 2;	/* relative timestamp */
1591590Srgrimes			break;
1601590Srgrimes		case 'T':
1611590Srgrimes			timestamp = 1;
1621590Srgrimes			break;
1631590Srgrimes		case 't':
1641590Srgrimes			trpoints = getpoints(optarg);
16527443Scharnier			if (trpoints < 0)
16627443Scharnier				errx(1, "unknown trace point in %s", optarg);
1671590Srgrimes			break;
1681590Srgrimes		default:
1691590Srgrimes			usage();
1701590Srgrimes		}
1711590Srgrimes
17219853Sfenner	if (argc > optind)
1731590Srgrimes		usage();
1741590Srgrimes
1751590Srgrimes	m = (void *)malloc(size = 1025);
17627443Scharnier	if (m == NULL)
17727443Scharnier		errx(1, "%s", strerror(ENOMEM));
17827443Scharnier	if (!freopen(tracefile, "r", stdin))
17927443Scharnier		err(1, "%s", tracefile);
180112201Sjhb	drop_logged = 0;
1811590Srgrimes	while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) {
182112201Sjhb		if (ktr_header.ktr_type & KTR_DROP) {
183112201Sjhb			ktr_header.ktr_type &= ~KTR_DROP;
184151930Srwatson			if (!drop_logged && threads) {
185203551Sjh				(void)printf(
186203551Sjh				    "%6jd %6jd %-8.*s Events dropped.\n",
187203551Sjh				    (intmax_t)ktr_header.ktr_pid,
188203551Sjh				    ktr_header.ktr_tid > 0 ?
189203551Sjh				    (intmax_t)ktr_header.ktr_tid : 0,
190203551Sjh				    MAXCOMLEN, ktr_header.ktr_comm);
191151930Srwatson				drop_logged = 1;
192151930Srwatson			} else if (!drop_logged) {
193203551Sjh				(void)printf("%6jd %-8.*s Events dropped.\n",
194203551Sjh				    (intmax_t)ktr_header.ktr_pid, MAXCOMLEN,
195112201Sjhb				    ktr_header.ktr_comm);
196112201Sjhb				drop_logged = 1;
197112201Sjhb			}
198112201Sjhb		}
1991590Srgrimes		if (trpoints & (1<<ktr_header.ktr_type))
200115759Speter			if (pid == 0 || ktr_header.ktr_pid == pid)
201115759Speter				dumpheader(&ktr_header);
20227443Scharnier		if ((ktrlen = ktr_header.ktr_len) < 0)
20327443Scharnier			errx(1, "bogus length 0x%x", ktrlen);
2041590Srgrimes		if (ktrlen > size) {
2051590Srgrimes			m = (void *)realloc(m, ktrlen+1);
20627443Scharnier			if (m == NULL)
20727443Scharnier				errx(1, "%s", strerror(ENOMEM));
2081590Srgrimes			size = ktrlen;
2091590Srgrimes		}
21027443Scharnier		if (ktrlen && fread_tail(m, ktrlen, 1) == 0)
21127443Scharnier			errx(1, "data too short");
212115759Speter		if (pid && ktr_header.ktr_pid != pid)
213115759Speter			continue;
2141590Srgrimes		if ((trpoints & (1<<ktr_header.ktr_type)) == 0)
2151590Srgrimes			continue;
216112201Sjhb		drop_logged = 0;
2171590Srgrimes		switch (ktr_header.ktr_type) {
2181590Srgrimes		case KTR_SYSCALL:
2191590Srgrimes			ktrsyscall((struct ktr_syscall *)m);
2201590Srgrimes			break;
2211590Srgrimes		case KTR_SYSRET:
2221590Srgrimes			ktrsysret((struct ktr_sysret *)m);
2231590Srgrimes			break;
2241590Srgrimes		case KTR_NAMEI:
225189707Sjhb		case KTR_SYSCTL:
2261590Srgrimes			ktrnamei(m, ktrlen);
2271590Srgrimes			break;
2281590Srgrimes		case KTR_GENIO:
2291590Srgrimes			ktrgenio((struct ktr_genio *)m, ktrlen);
2301590Srgrimes			break;
2311590Srgrimes		case KTR_PSIG:
2321590Srgrimes			ktrpsig((struct ktr_psig *)m);
2331590Srgrimes			break;
2341590Srgrimes		case KTR_CSW:
2351590Srgrimes			ktrcsw((struct ktr_csw *)m);
2361590Srgrimes			break;
23718400Sphk		case KTR_USER:
23818470Sphk			ktruser(ktrlen, m);
23918400Sphk			break;
240176471Sdes		case KTR_STRUCT:
241176471Sdes			ktrstruct(m, ktrlen);
242176471Sdes			break;
243112203Sjhb		default:
244112203Sjhb			printf("\n");
245112203Sjhb			break;
2461590Srgrimes		}
2471590Srgrimes		if (tail)
2481590Srgrimes			(void)fflush(stdout);
2491590Srgrimes	}
250100824Sdwmalone	return 0;
2511590Srgrimes}
2521590Srgrimes
253100824Sdwmaloneint
254100824Sdwmalonefread_tail(void *buf, int size, int num)
2551590Srgrimes{
2561590Srgrimes	int i;
2571590Srgrimes
2581590Srgrimes	while ((i = fread(buf, size, num, stdin)) == 0 && tail) {
2591590Srgrimes		(void)sleep(1);
2601590Srgrimes		clearerr(stdin);
2611590Srgrimes	}
2621590Srgrimes	return (i);
2631590Srgrimes}
2641590Srgrimes
265100824Sdwmalonevoid
266100824Sdwmalonedumpheader(struct ktr_header *kth)
2671590Srgrimes{
2681590Srgrimes	static char unknown[64];
2691590Srgrimes	static struct timeval prevtime, temp;
270100824Sdwmalone	const char *type;
2711590Srgrimes
2721590Srgrimes	switch (kth->ktr_type) {
2731590Srgrimes	case KTR_SYSCALL:
2741590Srgrimes		type = "CALL";
2751590Srgrimes		break;
2761590Srgrimes	case KTR_SYSRET:
2771590Srgrimes		type = "RET ";
2781590Srgrimes		break;
2791590Srgrimes	case KTR_NAMEI:
2801590Srgrimes		type = "NAMI";
2811590Srgrimes		break;
2821590Srgrimes	case KTR_GENIO:
2831590Srgrimes		type = "GIO ";
2841590Srgrimes		break;
2851590Srgrimes	case KTR_PSIG:
2861590Srgrimes		type = "PSIG";
2871590Srgrimes		break;
2881590Srgrimes	case KTR_CSW:
289171333Sjhb		type = "CSW ";
2901590Srgrimes		break;
29118400Sphk	case KTR_USER:
29218400Sphk		type = "USER";
29318400Sphk		break;
294176471Sdes	case KTR_STRUCT:
295176471Sdes		type = "STRU";
296176471Sdes		break;
297189707Sjhb	case KTR_SYSCTL:
298189707Sjhb		type = "SCTL";
299189707Sjhb		break;
3001590Srgrimes	default:
3011590Srgrimes		(void)sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type);
3021590Srgrimes		type = unknown;
3031590Srgrimes	}
3041590Srgrimes
305151930Srwatson	/*
306151930Srwatson	 * The ktr_tid field was previously the ktr_buffer field, which held
307151930Srwatson	 * the kernel pointer value for the buffer associated with data
308151930Srwatson	 * following the record header.  It now holds a threadid, but only
309151930Srwatson	 * for trace files after the change.  Older trace files still contain
310151930Srwatson	 * kernel pointers.  Detect this and suppress the results by printing
311151930Srwatson	 * negative tid's as 0.
312151930Srwatson	 */
313151930Srwatson	if (threads)
314203551Sjh		(void)printf("%6jd %6jd %-8.*s ", (intmax_t)kth->ktr_pid,
315203551Sjh		    kth->ktr_tid > 0 ? (intmax_t)kth->ktr_tid : 0,
316203551Sjh		    MAXCOMLEN, kth->ktr_comm);
317151930Srwatson	else
318203551Sjh		(void)printf("%6jd %-8.*s ", (intmax_t)kth->ktr_pid, MAXCOMLEN,
319151930Srwatson		    kth->ktr_comm);
3201590Srgrimes	if (timestamp) {
321123187Speter		if (timestamp == 3) {
322123187Speter			if (prevtime.tv_sec == 0)
323123187Speter				prevtime = kth->ktr_time;
324123187Speter			timevalsub(&kth->ktr_time, &prevtime);
325123187Speter		}
3261590Srgrimes		if (timestamp == 2) {
3271590Srgrimes			temp = kth->ktr_time;
3281590Srgrimes			timevalsub(&kth->ktr_time, &prevtime);
3291590Srgrimes			prevtime = temp;
3301590Srgrimes		}
331203551Sjh		(void)printf("%jd.%06ld ", (intmax_t)kth->ktr_time.tv_sec,
332203551Sjh		    kth->ktr_time.tv_usec);
3331590Srgrimes	}
3341590Srgrimes	(void)printf("%s  ", type);
3351590Srgrimes}
3361590Srgrimes
3371590Srgrimes#include <sys/syscall.h>
3381590Srgrimes#define KTRACE
3394721Sphk#include <sys/kern/syscalls.c>
3401590Srgrimes#undef KTRACE
3411590Srgrimesint nsyscalls = sizeof (syscallnames) / sizeof (syscallnames[0]);
3421590Srgrimes
343100824Sdwmalonevoid
344100824Sdwmalonektrsyscall(struct ktr_syscall *ktr)
3451590Srgrimes{
346100824Sdwmalone	int narg = ktr->ktr_narg;
347100824Sdwmalone	register_t *ip;
3481590Srgrimes
3491590Srgrimes	if (ktr->ktr_code >= nsyscalls || ktr->ktr_code < 0)
3501590Srgrimes		(void)printf("[%d]", ktr->ktr_code);
3511590Srgrimes	else
3521590Srgrimes		(void)printf("%s", syscallnames[ktr->ktr_code]);
35347957Sdt	ip = &ktr->ktr_args[0];
3541590Srgrimes	if (narg) {
3551590Srgrimes		char c = '(';
3561590Srgrimes		if (fancy) {
357158766Snetchild
358158766Snetchild#define print_number(i,n,c) do {                      \
359158766Snetchild	if (decimal)                                  \
360158766Snetchild		(void)printf("%c%ld", c, (long)*i);   \
361158766Snetchild	else                                          \
362158766Snetchild		(void)printf("%c%#lx", c, (long)*i);  \
363158766Snetchild	i++;                                          \
364158766Snetchild	n--;                                          \
365158766Snetchild	c = ',';                                      \
366158766Snetchild	} while (0);
367158766Snetchild
3681590Srgrimes			if (ktr->ktr_code == SYS_ioctl) {
369100824Sdwmalone				const char *cp;
370158766Snetchild				print_number(ip,narg,c);
3711590Srgrimes				if ((cp = ioctlname(*ip)) != NULL)
3721590Srgrimes					(void)printf(",%s", cp);
3731590Srgrimes				else {
3741590Srgrimes					if (decimal)
37547957Sdt						(void)printf(",%ld", (long)*ip);
3761590Srgrimes					else
37747957Sdt						(void)printf(",%#lx ", (long)*ip);
3781590Srgrimes				}
3791590Srgrimes				c = ',';
3801590Srgrimes				ip++;
3811590Srgrimes				narg--;
3821590Srgrimes			} else if (ktr->ktr_code == SYS_ptrace) {
383168543Semaste				(void)putchar('(');
384168543Semaste				ptraceopname ((int)*ip);
3851590Srgrimes				c = ',';
3861590Srgrimes				ip++;
3871590Srgrimes				narg--;
388158766Snetchild			} else if (ktr->ktr_code == SYS_access ||
389158766Snetchild				   ktr->ktr_code == SYS_eaccess) {
390158766Snetchild				print_number(ip,narg,c);
391158766Snetchild				(void)putchar(',');
392158766Snetchild				accessmodename ((int)*ip);
393158766Snetchild				ip++;
394158766Snetchild				narg--;
395158766Snetchild			} else if (ktr->ktr_code == SYS_open) {
396158766Snetchild				int	flags;
397158766Snetchild				int	mode;
398158766Snetchild				print_number(ip,narg,c);
399158766Snetchild				flags = *ip;
400158766Snetchild				mode = *++ip;
401158766Snetchild				(void)putchar(',');
402158766Snetchild				flagsandmodename (flags, mode, decimal);
403158766Snetchild				ip++;
404158766Snetchild				narg-=2;
405158766Snetchild			} else if (ktr->ktr_code == SYS_wait4) {
406158766Snetchild				print_number(ip,narg,c);
407158766Snetchild				print_number(ip,narg,c);
408158766Snetchild				(void)putchar(',');
409158766Snetchild				wait4optname ((int)*ip);
410158766Snetchild				ip++;
411158766Snetchild				narg--;
412158766Snetchild			} else if (ktr->ktr_code == SYS_chmod ||
413158766Snetchild				   ktr->ktr_code == SYS_fchmod ||
414158766Snetchild				   ktr->ktr_code == SYS_lchmod) {
415158766Snetchild				print_number(ip,narg,c);
416158766Snetchild				(void)putchar(',');
417158766Snetchild				modename ((int)*ip);
418158766Snetchild				ip++;
419158766Snetchild				narg--;
420158766Snetchild			} else if (ktr->ktr_code == SYS_mknod) {
421158766Snetchild				print_number(ip,narg,c);
422158766Snetchild				(void)putchar(',');
423158766Snetchild				modename ((int)*ip);
424158766Snetchild				ip++;
425158766Snetchild				narg--;
426158766Snetchild			} else if (ktr->ktr_code == SYS_getfsstat) {
427158766Snetchild				print_number(ip,narg,c);
428158766Snetchild				print_number(ip,narg,c);
429158766Snetchild				(void)putchar(',');
430158766Snetchild				getfsstatflagsname ((int)*ip);
431158766Snetchild				ip++;
432158766Snetchild				narg--;
433158766Snetchild			} else if (ktr->ktr_code == SYS_mount) {
434158766Snetchild				print_number(ip,narg,c);
435158766Snetchild				print_number(ip,narg,c);
436158766Snetchild				(void)putchar(',');
437158766Snetchild				mountflagsname ((int)*ip);
438158766Snetchild				ip++;
439158766Snetchild				narg--;
440158766Snetchild			} else if (ktr->ktr_code == SYS_unmount) {
441158766Snetchild				print_number(ip,narg,c);
442158766Snetchild				(void)putchar(',');
443158766Snetchild				mountflagsname ((int)*ip);
444158766Snetchild				ip++;
445158766Snetchild				narg--;
446158766Snetchild			} else if (ktr->ktr_code == SYS_recvmsg ||
447158766Snetchild				   ktr->ktr_code == SYS_sendmsg) {
448158766Snetchild				print_number(ip,narg,c);
449158766Snetchild				print_number(ip,narg,c);
450158766Snetchild				(void)putchar(',');
451158766Snetchild				sendrecvflagsname ((int)*ip);
452158766Snetchild				ip++;
453158766Snetchild				narg--;
454158766Snetchild			} else if (ktr->ktr_code == SYS_recvfrom ||
455158766Snetchild				   ktr->ktr_code == SYS_sendto) {
456158766Snetchild				print_number(ip,narg,c);
457158766Snetchild				print_number(ip,narg,c);
458158766Snetchild				print_number(ip,narg,c);
459158766Snetchild				(void)putchar(',');
460158766Snetchild				sendrecvflagsname ((int)*ip);
461158766Snetchild				ip++;
462158766Snetchild				narg--;
463158766Snetchild			} else if (ktr->ktr_code == SYS_chflags ||
464158766Snetchild				   ktr->ktr_code == SYS_fchflags ||
465158766Snetchild				   ktr->ktr_code == SYS_lchflags) {
466158766Snetchild				print_number(ip,narg,c);
467158766Snetchild				(void)putchar(',');
468158766Snetchild				modename((int)*ip);
469158766Snetchild				ip++;
470158766Snetchild				narg--;
471158766Snetchild			} else if (ktr->ktr_code == SYS_kill) {
472158766Snetchild				print_number(ip,narg,c);
473158766Snetchild				(void)putchar(',');
474158766Snetchild				signame((int)*ip);
475158766Snetchild				ip++;
476158766Snetchild				narg--;
477158766Snetchild			} else if (ktr->ktr_code == SYS_reboot) {
478158766Snetchild				(void)putchar('(');
479158766Snetchild				rebootoptname((int)*ip);
480158766Snetchild				ip++;
481158766Snetchild				narg--;
482158766Snetchild			} else if (ktr->ktr_code == SYS_umask) {
483158766Snetchild				(void)putchar('(');
484158766Snetchild				modename((int)*ip);
485158766Snetchild				ip++;
486158766Snetchild				narg--;
487158766Snetchild			} else if (ktr->ktr_code == SYS_msync) {
488158766Snetchild				print_number(ip,narg,c);
489158766Snetchild				print_number(ip,narg,c);
490158766Snetchild				(void)putchar(',');
491158766Snetchild				msyncflagsname((int)*ip);
492158766Snetchild				ip++;
493158766Snetchild				narg--;
494171221Speter#ifdef SYS_freebsd6_mmap
495171221Speter			} else if (ktr->ktr_code == SYS_freebsd6_mmap) {
496171221Speter				print_number(ip,narg,c);
497171221Speter				print_number(ip,narg,c);
498171221Speter				(void)putchar(',');
499171221Speter				mmapprotname ((int)*ip);
500171221Speter				(void)putchar(',');
501171221Speter				ip++;
502171221Speter				narg--;
503171221Speter				mmapflagsname ((int)*ip);
504171221Speter				ip++;
505171221Speter				narg--;
506171221Speter#endif
507158766Snetchild			} else if (ktr->ktr_code == SYS_mmap) {
508158766Snetchild				print_number(ip,narg,c);
509158766Snetchild				print_number(ip,narg,c);
510158766Snetchild				(void)putchar(',');
511158766Snetchild				mmapprotname ((int)*ip);
512158766Snetchild				(void)putchar(',');
513158766Snetchild				ip++;
514158766Snetchild				narg--;
515158766Snetchild				mmapflagsname ((int)*ip);
516158766Snetchild				ip++;
517158766Snetchild				narg--;
518158766Snetchild			} else if (ktr->ktr_code == SYS_mprotect) {
519158766Snetchild				print_number(ip,narg,c);
520158766Snetchild				print_number(ip,narg,c);
521158766Snetchild				(void)putchar(',');
522158766Snetchild				mmapprotname ((int)*ip);
523158766Snetchild				ip++;
524158766Snetchild				narg--;
525158766Snetchild			} else if (ktr->ktr_code == SYS_madvise) {
526158766Snetchild				print_number(ip,narg,c);
527158766Snetchild				print_number(ip,narg,c);
528158766Snetchild				(void)putchar(',');
529158766Snetchild				madvisebehavname((int)*ip);
530158766Snetchild				ip++;
531158766Snetchild				narg--;
532158766Snetchild			} else if (ktr->ktr_code == SYS_setpriority) {
533158766Snetchild				print_number(ip,narg,c);
534158766Snetchild				print_number(ip,narg,c);
535158766Snetchild				(void)putchar(',');
536158766Snetchild				prioname((int)*ip);
537158766Snetchild				ip++;
538158766Snetchild				narg--;
539158766Snetchild			} else if (ktr->ktr_code == SYS_fcntl) {
540158766Snetchild				int cmd;
541158766Snetchild				int arg;
542158766Snetchild				print_number(ip,narg,c);
543158766Snetchild				cmd = *ip;
544158766Snetchild				arg = *++ip;
545158766Snetchild				(void)putchar(',');
546158766Snetchild				fcntlcmdname(cmd, arg, decimal);
547158766Snetchild				ip++;
548158766Snetchild				narg-=2;
549158766Snetchild			} else if (ktr->ktr_code == SYS_socket) {
550165758Srodrigc				int sockdomain;
551158766Snetchild				(void)putchar('(');
552165758Srodrigc				sockdomain=(int)*ip;
553165758Srodrigc				sockdomainname(sockdomain);
554158766Snetchild				ip++;
555158766Snetchild				narg--;
556158766Snetchild				(void)putchar(',');
557158766Snetchild				socktypename((int)*ip);
558158766Snetchild				ip++;
559158766Snetchild				narg--;
560165758Srodrigc				if (sockdomain == PF_INET ||
561165758Srodrigc				    sockdomain == PF_INET6) {
562165758Srodrigc					(void)putchar(',');
563165758Srodrigc					sockipprotoname((int)*ip);
564165758Srodrigc					ip++;
565165758Srodrigc					narg--;
566165758Srodrigc				}
567158766Snetchild				c = ',';
568158766Snetchild			} else if (ktr->ktr_code == SYS_setsockopt ||
569158766Snetchild				   ktr->ktr_code == SYS_getsockopt) {
570158766Snetchild				print_number(ip,narg,c);
571158766Snetchild				(void)putchar(',');
572158766Snetchild				sockoptlevelname((int)*ip, decimal);
573175138Sjhb				if ((int)*ip == SOL_SOCKET) {
574175138Sjhb					ip++;
575175138Sjhb					narg--;
576175138Sjhb					(void)putchar(',');
577175138Sjhb					sockoptname((int)*ip);
578175138Sjhb				}
579158766Snetchild				ip++;
580158766Snetchild				narg--;
581171221Speter#ifdef SYS_freebsd6_lseek
582171221Speter			} else if (ktr->ktr_code == SYS_freebsd6_lseek) {
583158766Snetchild				print_number(ip,narg,c);
584158766Snetchild				/* Hidden 'pad' argument, not in lseek(2) */
585158766Snetchild				print_number(ip,narg,c);
586158766Snetchild				print_number(ip,narg,c);
587158766Snetchild				(void)putchar(',');
588158766Snetchild				whencename ((int)*ip);
589158766Snetchild				ip++;
590158766Snetchild				narg--;
591171221Speter#endif
592171221Speter			} else if (ktr->ktr_code == SYS_lseek) {
593171221Speter				print_number(ip,narg,c);
594171221Speter				/* Hidden 'pad' argument, not in lseek(2) */
595171221Speter				print_number(ip,narg,c);
596171221Speter				(void)putchar(',');
597171221Speter				whencename ((int)*ip);
598171221Speter				ip++;
599171221Speter				narg--;
600171221Speter
601158766Snetchild			} else if (ktr->ktr_code == SYS_flock) {
602158766Snetchild				print_number(ip,narg,c);
603158766Snetchild				(void)putchar(',');
604158766Snetchild				flockname((int)*ip);
605158766Snetchild				ip++;
606158766Snetchild				narg--;
607158766Snetchild			} else if (ktr->ktr_code == SYS_mkfifo ||
608158766Snetchild				   ktr->ktr_code == SYS_mkdir) {
609158766Snetchild				print_number(ip,narg,c);
610158766Snetchild				(void)putchar(',');
611158766Snetchild				modename((int)*ip);
612158766Snetchild				ip++;
613158766Snetchild				narg--;
614158766Snetchild			} else if (ktr->ktr_code == SYS_shutdown) {
615158766Snetchild				print_number(ip,narg,c);
616158766Snetchild				(void)putchar(',');
617158766Snetchild				shutdownhowname((int)*ip);
618158766Snetchild				ip++;
619158766Snetchild				narg--;
620158766Snetchild			} else if (ktr->ktr_code == SYS_socketpair) {
621158766Snetchild				(void)putchar('(');
622158766Snetchild				sockdomainname((int)*ip);
623158766Snetchild				ip++;
624158766Snetchild				narg--;
625158766Snetchild				(void)putchar(',');
626158766Snetchild				socktypename((int)*ip);
627158766Snetchild				ip++;
628158766Snetchild				narg--;
629158766Snetchild				c = ',';
630158766Snetchild			} else if (ktr->ktr_code == SYS_getrlimit ||
631158766Snetchild				   ktr->ktr_code == SYS_setrlimit) {
632158766Snetchild				(void)putchar('(');
633158766Snetchild				rlimitname((int)*ip);
634158766Snetchild				ip++;
635158766Snetchild				narg--;
636158766Snetchild				c = ',';
637158766Snetchild			} else if (ktr->ktr_code == SYS_quotactl) {
638158766Snetchild				print_number(ip,narg,c);
639174346Sjhb				(void)putchar(',');
640158766Snetchild				quotactlname((int)*ip);
641158766Snetchild				ip++;
642158766Snetchild				narg--;
643158766Snetchild				c = ',';
644158766Snetchild			} else if (ktr->ktr_code == SYS_nfssvc) {
645158766Snetchild				(void)putchar('(');
646158766Snetchild				nfssvcname((int)*ip);
647158766Snetchild				ip++;
648158766Snetchild				narg--;
649158766Snetchild				c = ',';
650158766Snetchild			} else if (ktr->ktr_code == SYS_rtprio) {
651158766Snetchild				(void)putchar('(');
652158766Snetchild				rtprioname((int)*ip);
653158766Snetchild				ip++;
654158766Snetchild				narg--;
655158766Snetchild				c = ',';
656158766Snetchild			} else if (ktr->ktr_code == SYS___semctl) {
657158766Snetchild				print_number(ip,narg,c);
658158766Snetchild				print_number(ip,narg,c);
659174346Sjhb				(void)putchar(',');
660158766Snetchild				semctlname((int)*ip);
661158766Snetchild				ip++;
662158766Snetchild				narg--;
663158766Snetchild			} else if (ktr->ktr_code == SYS_semget) {
664158766Snetchild				print_number(ip,narg,c);
665158766Snetchild				print_number(ip,narg,c);
666174346Sjhb				(void)putchar(',');
667158766Snetchild				semgetname((int)*ip);
668158766Snetchild				ip++;
669158766Snetchild				narg--;
670158766Snetchild			} else if (ktr->ktr_code == SYS_msgctl) {
671158766Snetchild				print_number(ip,narg,c);
672174346Sjhb				(void)putchar(',');
673158766Snetchild				shmctlname((int)*ip);
674158766Snetchild				ip++;
675158766Snetchild				narg--;
676158766Snetchild			} else if (ktr->ktr_code == SYS_shmat) {
677158766Snetchild				print_number(ip,narg,c);
678158766Snetchild				print_number(ip,narg,c);
679174346Sjhb				(void)putchar(',');
680158766Snetchild				shmatname((int)*ip);
681158766Snetchild				ip++;
682158766Snetchild				narg--;
683158766Snetchild			} else if (ktr->ktr_code == SYS_shmctl) {
684158766Snetchild				print_number(ip,narg,c);
685174346Sjhb				(void)putchar(',');
686158766Snetchild				shmctlname((int)*ip);
687158766Snetchild				ip++;
688158766Snetchild				narg--;
689158766Snetchild			} else if (ktr->ktr_code == SYS_minherit) {
690158766Snetchild				print_number(ip,narg,c);
691158766Snetchild				print_number(ip,narg,c);
692174346Sjhb				(void)putchar(',');
693158766Snetchild				minheritname((int)*ip);
694158766Snetchild				ip++;
695158766Snetchild				narg--;
696158766Snetchild			} else if (ktr->ktr_code == SYS_rfork) {
697158766Snetchild				(void)putchar('(');
698158766Snetchild				rforkname((int)*ip);
699158766Snetchild				ip++;
700158766Snetchild				narg--;
701158766Snetchild				c = ',';
702158766Snetchild			} else if (ktr->ktr_code == SYS_lio_listio) {
703158766Snetchild				(void)putchar('(');
704158766Snetchild				lio_listioname((int)*ip);
705158766Snetchild				ip++;
706158766Snetchild				narg--;
707158766Snetchild				c = ',';
708158766Snetchild			} else if (ktr->ktr_code == SYS_mlockall) {
709158766Snetchild				(void)putchar('(');
710158766Snetchild				mlockallname((int)*ip);
711158766Snetchild				ip++;
712158766Snetchild				narg--;
713158766Snetchild			} else if (ktr->ktr_code == SYS_sched_setscheduler) {
714158766Snetchild				print_number(ip,narg,c);
715174346Sjhb				(void)putchar(',');
716158766Snetchild				schedpolicyname((int)*ip);
717158766Snetchild				ip++;
718158766Snetchild				narg--;
719158766Snetchild			} else if (ktr->ktr_code == SYS_sched_get_priority_max ||
720158766Snetchild				   ktr->ktr_code == SYS_sched_get_priority_min) {
721158766Snetchild				(void)putchar('(');
722158766Snetchild				schedpolicyname((int)*ip);
723158766Snetchild				ip++;
724158766Snetchild				narg--;
725158766Snetchild			} else if (ktr->ktr_code == SYS_sendfile) {
726158766Snetchild				print_number(ip,narg,c);
727158766Snetchild				print_number(ip,narg,c);
728158766Snetchild				print_number(ip,narg,c);
729158766Snetchild				print_number(ip,narg,c);
730158766Snetchild				print_number(ip,narg,c);
731158766Snetchild				print_number(ip,narg,c);
732174346Sjhb				(void)putchar(',');
733158766Snetchild				sendfileflagsname((int)*ip);
734158766Snetchild				ip++;
735158766Snetchild				narg--;
736158766Snetchild			} else if (ktr->ktr_code == SYS_kldsym) {
737158766Snetchild				print_number(ip,narg,c);
738174346Sjhb				(void)putchar(',');
739158766Snetchild				kldsymcmdname((int)*ip);
740158766Snetchild				ip++;
741158766Snetchild				narg--;
742158766Snetchild			} else if (ktr->ktr_code == SYS_sigprocmask) {
743158766Snetchild				(void)putchar('(');
744158766Snetchild				sigprocmaskhowname((int)*ip);
745158766Snetchild				ip++;
746158766Snetchild				narg--;
747158766Snetchild				c = ',';
748158766Snetchild			} else if (ktr->ktr_code == SYS___acl_get_file ||
749158766Snetchild				   ktr->ktr_code == SYS___acl_set_file ||
750158766Snetchild				   ktr->ktr_code == SYS___acl_get_fd ||
751158766Snetchild				   ktr->ktr_code == SYS___acl_set_fd ||
752158766Snetchild				   ktr->ktr_code == SYS___acl_delete_file ||
753158766Snetchild				   ktr->ktr_code == SYS___acl_delete_fd ||
754158766Snetchild				   ktr->ktr_code == SYS___acl_aclcheck_file ||
755158766Snetchild				   ktr->ktr_code == SYS___acl_aclcheck_fd ||
756158766Snetchild				   ktr->ktr_code == SYS___acl_get_link ||
757158766Snetchild				   ktr->ktr_code == SYS___acl_set_link ||
758158766Snetchild				   ktr->ktr_code == SYS___acl_delete_link ||
759158766Snetchild				   ktr->ktr_code == SYS___acl_aclcheck_link) {
760158766Snetchild				print_number(ip,narg,c);
761174346Sjhb				(void)putchar(',');
762158766Snetchild				acltypename((int)*ip);
763158766Snetchild				ip++;
764158766Snetchild				narg--;
765158766Snetchild			} else if (ktr->ktr_code == SYS_sigaction) {
766158766Snetchild				(void)putchar('(');
767158766Snetchild				signame((int)*ip);
768158766Snetchild				ip++;
769158766Snetchild				narg--;
770158766Snetchild				c = ',';
771158766Snetchild			} else if (ktr->ktr_code == SYS_extattrctl) {
772158766Snetchild				print_number(ip,narg,c);
773174346Sjhb				(void)putchar(',');
774158766Snetchild				extattrctlname((int)*ip);
775158766Snetchild				ip++;
776158766Snetchild				narg--;
777158766Snetchild			} else if (ktr->ktr_code == SYS_nmount) {
778158766Snetchild				print_number(ip,narg,c);
779158766Snetchild				print_number(ip,narg,c);
780158766Snetchild				(void)putchar(',');
781158766Snetchild				mountflagsname ((int)*ip);
782158766Snetchild				ip++;
783158766Snetchild				narg--;
784158766Snetchild			} else if (ktr->ktr_code == SYS_thr_create) {
785158766Snetchild				print_number(ip,narg,c);
786158766Snetchild				print_number(ip,narg,c);
787158766Snetchild				(void)putchar(',');
788158766Snetchild				thrcreateflagsname ((int)*ip);
789158766Snetchild				ip++;
790158766Snetchild				narg--;
791158766Snetchild			} else if (ktr->ktr_code == SYS_thr_kill) {
792158766Snetchild				print_number(ip,narg,c);
793158766Snetchild				(void)putchar(',');
794158766Snetchild				signame ((int)*ip);
795158766Snetchild				ip++;
796158766Snetchild				narg--;
797158766Snetchild			} else if (ktr->ktr_code == SYS_kldunloadf) {
798158766Snetchild				print_number(ip,narg,c);
799158766Snetchild				(void)putchar(',');
800158766Snetchild				kldunloadfflagsname ((int)*ip);
801158766Snetchild				ip++;
802158766Snetchild				narg--;
8031590Srgrimes			}
8041590Srgrimes		}
805199024Sattilio		while (narg > 0) {
806158766Snetchild			print_number(ip,narg,c);
8071590Srgrimes		}
8081590Srgrimes		(void)putchar(')');
8091590Srgrimes	}
8101590Srgrimes	(void)putchar('\n');
8111590Srgrimes}
8121590Srgrimes
813100824Sdwmalonevoid
814100824Sdwmalonektrsysret(struct ktr_sysret *ktr)
8151590Srgrimes{
816100824Sdwmalone	register_t ret = ktr->ktr_retval;
817100824Sdwmalone	int error = ktr->ktr_error;
818100824Sdwmalone	int code = ktr->ktr_code;
8191590Srgrimes
8201590Srgrimes	if (code >= nsyscalls || code < 0)
8211590Srgrimes		(void)printf("[%d] ", code);
8221590Srgrimes	else
8231590Srgrimes		(void)printf("%s ", syscallnames[code]);
8241590Srgrimes
8251590Srgrimes	if (error == 0) {
8261590Srgrimes		if (fancy) {
827203551Sjh			(void)printf("%ld", (long)ret);
8281590Srgrimes			if (ret < 0 || ret > 9)
82947957Sdt				(void)printf("/%#lx", (long)ret);
8301590Srgrimes		} else {
8311590Srgrimes			if (decimal)
83247957Sdt				(void)printf("%ld", (long)ret);
8331590Srgrimes			else
83447957Sdt				(void)printf("%#lx", (long)ret);
8351590Srgrimes		}
8361590Srgrimes	} else if (error == ERESTART)
8371590Srgrimes		(void)printf("RESTART");
8381590Srgrimes	else if (error == EJUSTRETURN)
8391590Srgrimes		(void)printf("JUSTRETURN");
8401590Srgrimes	else {
8411590Srgrimes		(void)printf("-1 errno %d", ktr->ktr_error);
8421590Srgrimes		if (fancy)
8431590Srgrimes			(void)printf(" %s", strerror(ktr->ktr_error));
8441590Srgrimes	}
8451590Srgrimes	(void)putchar('\n');
8461590Srgrimes}
8471590Srgrimes
848100824Sdwmalonevoid
849100824Sdwmalonektrnamei(char *cp, int len)
8501590Srgrimes{
8511590Srgrimes	(void)printf("\"%.*s\"\n", len, cp);
8521590Srgrimes}
8531590Srgrimes
854100824Sdwmalonevoid
855115759Speterhexdump(char *p, int len, int screenwidth)
8561590Srgrimes{
857115759Speter	int n, i;
858115759Speter	int width;
859115759Speter
860115759Speter	width = 0;
861115759Speter	do {
862115759Speter		width += 2;
863115759Speter		i = 13;			/* base offset */
864115759Speter		i += (width / 2) + 1;	/* spaces every second byte */
865115759Speter		i += (width * 2);	/* width of bytes */
866115759Speter		i += 3;			/* "  |" */
867115759Speter		i += width;		/* each byte */
868115759Speter		i += 1;			/* "|" */
869115759Speter	} while (i < screenwidth);
870115759Speter	width -= 2;
871115759Speter
872115759Speter	for (n = 0; n < len; n += width) {
873115759Speter		for (i = n; i < n + width; i++) {
874115759Speter			if ((i % width) == 0) {	/* beginning of line */
875115759Speter				printf("       0x%04x", i);
876115759Speter			}
877115759Speter			if ((i % 2) == 0) {
878115759Speter				printf(" ");
879115759Speter			}
880115759Speter			if (i < len)
881115759Speter				printf("%02x", p[i] & 0xff);
882115759Speter			else
883115759Speter				printf("  ");
884115759Speter		}
885115759Speter		printf("  |");
886115759Speter		for (i = n; i < n + width; i++) {
887115759Speter			if (i >= len)
888115759Speter				break;
889115759Speter			if (p[i] >= ' ' && p[i] <= '~')
890115759Speter				printf("%c", p[i]);
891115759Speter			else
892115759Speter				printf(".");
893115759Speter		}
894115759Speter		printf("|\n");
895115759Speter	}
896115759Speter	if ((i % width) != 0)
897115759Speter		printf("\n");
898115759Speter}
899115759Speter
900115759Spetervoid
901115759Spetervisdump(char *dp, int datalen, int screenwidth)
902115759Speter{
903115759Speter	int col = 0;
904100824Sdwmalone	char *cp;
905100824Sdwmalone	int width;
9061590Srgrimes	char visbuf[5];
9071590Srgrimes
9081590Srgrimes	(void)printf("       \"");
9091590Srgrimes	col = 8;
9101590Srgrimes	for (;datalen > 0; datalen--, dp++) {
9111590Srgrimes		(void) vis(visbuf, *dp, VIS_CSTYLE, *(dp+1));
9121590Srgrimes		cp = visbuf;
9131590Srgrimes		/*
9141590Srgrimes		 * Keep track of printables and
9151590Srgrimes		 * space chars (like fold(1)).
9161590Srgrimes		 */
9171590Srgrimes		if (col == 0) {
9181590Srgrimes			(void)putchar('\t');
9191590Srgrimes			col = 8;
9201590Srgrimes		}
9211590Srgrimes		switch(*cp) {
9221590Srgrimes		case '\n':
9231590Srgrimes			col = 0;
9241590Srgrimes			(void)putchar('\n');
9251590Srgrimes			continue;
9261590Srgrimes		case '\t':
9271590Srgrimes			width = 8 - (col&07);
9281590Srgrimes			break;
9291590Srgrimes		default:
9301590Srgrimes			width = strlen(cp);
9311590Srgrimes		}
9321590Srgrimes		if (col + width > (screenwidth-2)) {
9331590Srgrimes			(void)printf("\\\n\t");
9341590Srgrimes			col = 8;
9351590Srgrimes		}
9361590Srgrimes		col += width;
9371590Srgrimes		do {
9381590Srgrimes			(void)putchar(*cp++);
9391590Srgrimes		} while (*cp);
9401590Srgrimes	}
9411590Srgrimes	if (col == 0)
9421590Srgrimes		(void)printf("       ");
9431590Srgrimes	(void)printf("\"\n");
9441590Srgrimes}
9451590Srgrimes
946115759Spetervoid
947115759Speterktrgenio(struct ktr_genio *ktr, int len)
948115759Speter{
949115759Speter	int datalen = len - sizeof (struct ktr_genio);
950115759Speter	char *dp = (char *)ktr + sizeof (struct ktr_genio);
951115759Speter	static int screenwidth = 0;
952115759Speter	int i, binary;
953115759Speter
954115759Speter	if (screenwidth == 0) {
955115759Speter		struct winsize ws;
956115759Speter
957115759Speter		if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 &&
958115759Speter		    ws.ws_col > 8)
959115759Speter			screenwidth = ws.ws_col;
960115759Speter		else
961115759Speter			screenwidth = 80;
962115759Speter	}
963115759Speter	printf("fd %d %s %d byte%s\n", ktr->ktr_fd,
964115759Speter		ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen,
965115759Speter		datalen == 1 ? "" : "s");
966152331Srwatson	if (suppressdata)
967152331Srwatson		return;
968115759Speter	if (maxdata && datalen > maxdata)
969115759Speter		datalen = maxdata;
970115759Speter
971115759Speter	for (i = 0, binary = 0; i < datalen && binary == 0; i++)  {
972115759Speter		if (dp[i] >= 32 && dp[i] < 127)
973115759Speter			continue;
974115759Speter		if (dp[i] == 10 || dp[i] == 13 || dp[i] == 0 || dp[i] == 9)
975115759Speter			continue;
976115759Speter		binary = 1;
977115759Speter	}
978115759Speter	if (binary)
979115759Speter		hexdump(dp, datalen, screenwidth);
980115759Speter	else
981115759Speter		visdump(dp, datalen, screenwidth);
982115759Speter}
983115759Speter
984100824Sdwmaloneconst char *signames[] = {
9851590Srgrimes	"NULL", "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT",	/*  1 - 6  */
9861590Srgrimes	"EMT", "FPE", "KILL", "BUS", "SEGV", "SYS",		/*  7 - 12 */
9871590Srgrimes	"PIPE", "ALRM",  "TERM", "URG", "STOP", "TSTP",		/* 13 - 18 */
9881590Srgrimes	"CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU",		/* 19 - 24 */
9891590Srgrimes	"XFSZ", "VTALRM", "PROF", "WINCH", "29", "USR1",	/* 25 - 30 */
9901590Srgrimes	"USR2", NULL,						/* 31 - 32 */
9911590Srgrimes};
9921590Srgrimes
993100824Sdwmalonevoid
994100824Sdwmalonektrpsig(struct ktr_psig *psig)
9951590Srgrimes{
996160294Skib	if (psig->signo > 0 && psig->signo < NSIG)
997160296Smaxim		(void)printf("SIG%s ", signames[psig->signo]);
998160294Skib	else
999160296Smaxim		(void)printf("SIG %d ", psig->signo);
10001590Srgrimes	if (psig->action == SIG_DFL)
10011590Srgrimes		(void)printf("SIG_DFL\n");
1002100824Sdwmalone	else {
100347957Sdt		(void)printf("caught handler=0x%lx mask=0x%x code=0x%x\n",
1004100824Sdwmalone		    (u_long)psig->action, psig->mask.__bits[0], psig->code);
1005100824Sdwmalone	}
10061590Srgrimes}
10071590Srgrimes
1008100824Sdwmalonevoid
1009100824Sdwmalonektrcsw(struct ktr_csw *cs)
10101590Srgrimes{
10111590Srgrimes	(void)printf("%s %s\n", cs->out ? "stop" : "resume",
10121590Srgrimes		cs->user ? "user" : "kernel");
10131590Srgrimes}
10141590Srgrimes
1015165916Sjhb#define	UTRACE_DLOPEN_START		1
1016165916Sjhb#define	UTRACE_DLOPEN_STOP		2
1017165916Sjhb#define	UTRACE_DLCLOSE_START		3
1018165916Sjhb#define	UTRACE_DLCLOSE_STOP		4
1019165916Sjhb#define	UTRACE_LOAD_OBJECT		5
1020165916Sjhb#define	UTRACE_UNLOAD_OBJECT		6
1021165916Sjhb#define	UTRACE_ADD_RUNDEP		7
1022165916Sjhb#define	UTRACE_PRELOAD_FINISHED		8
1023165916Sjhb#define	UTRACE_INIT_CALL		9
1024165916Sjhb#define	UTRACE_FINI_CALL		10
1025165916Sjhb
1026165916Sjhbstruct utrace_rtld {
1027165916Sjhb	char sig[4];				/* 'RTLD' */
1028165916Sjhb	int event;
1029165916Sjhb	void *handle;
1030165916Sjhb	void *mapbase;
1031165916Sjhb	size_t mapsize;
1032165916Sjhb	int refcnt;
1033165916Sjhb	char name[MAXPATHLEN];
1034165916Sjhb};
1035165916Sjhb
1036165916Sjhbvoid
1037165916Sjhbktruser_rtld(int len, unsigned char *p)
1038165916Sjhb{
1039165916Sjhb	struct utrace_rtld *ut = (struct utrace_rtld *)p;
1040165916Sjhb	void *parent;
1041165916Sjhb	int mode;
1042165916Sjhb
1043165916Sjhb	switch (ut->event) {
1044165916Sjhb	case UTRACE_DLOPEN_START:
1045165916Sjhb		mode = ut->refcnt;
1046165916Sjhb		printf("dlopen(%s, ", ut->name);
1047165916Sjhb		switch (mode & RTLD_MODEMASK) {
1048165916Sjhb		case RTLD_NOW:
1049165916Sjhb			printf("RTLD_NOW");
1050165916Sjhb			break;
1051165916Sjhb		case RTLD_LAZY:
1052165916Sjhb			printf("RTLD_LAZY");
1053165916Sjhb			break;
1054165916Sjhb		default:
1055165916Sjhb			printf("%#x", mode & RTLD_MODEMASK);
1056165916Sjhb		}
1057165916Sjhb		if (mode & RTLD_GLOBAL)
1058165916Sjhb			printf(" | RTLD_GLOBAL");
1059165916Sjhb		if (mode & RTLD_TRACE)
1060165916Sjhb			printf(" | RTLD_TRACE");
1061165916Sjhb		if (mode & ~(RTLD_MODEMASK | RTLD_GLOBAL | RTLD_TRACE))
1062165916Sjhb			printf(" | %#x", mode &
1063165916Sjhb			    ~(RTLD_MODEMASK | RTLD_GLOBAL | RTLD_TRACE));
1064165916Sjhb		printf(")\n");
1065165916Sjhb		break;
1066165916Sjhb	case UTRACE_DLOPEN_STOP:
1067165916Sjhb		printf("%p = dlopen(%s) ref %d\n", ut->handle, ut->name,
1068165916Sjhb		    ut->refcnt);
1069165916Sjhb		break;
1070165916Sjhb	case UTRACE_DLCLOSE_START:
1071165916Sjhb		printf("dlclose(%p) (%s, %d)\n", ut->handle, ut->name,
1072165916Sjhb		    ut->refcnt);
1073165916Sjhb		break;
1074165916Sjhb	case UTRACE_DLCLOSE_STOP:
1075165916Sjhb		printf("dlclose(%p) finished\n", ut->handle);
1076165916Sjhb		break;
1077165916Sjhb	case UTRACE_LOAD_OBJECT:
1078165916Sjhb		printf("RTLD: loaded   %p @ %p - %p (%s)\n", ut->handle,
1079165916Sjhb		    ut->mapbase, (char *)ut->mapbase + ut->mapsize - 1,
1080165916Sjhb		    ut->name);
1081165916Sjhb		break;
1082165916Sjhb	case UTRACE_UNLOAD_OBJECT:
1083165916Sjhb		printf("RTLD: unloaded %p @ %p - %p (%s)\n", ut->handle,
1084165916Sjhb		    ut->mapbase, (char *)ut->mapbase + ut->mapsize - 1,
1085165916Sjhb		    ut->name);
1086165916Sjhb		break;
1087165916Sjhb	case UTRACE_ADD_RUNDEP:
1088165916Sjhb		parent = ut->mapbase;
1089165916Sjhb		printf("RTLD: %p now depends on %p (%s, %d)\n", parent,
1090165916Sjhb		    ut->handle, ut->name, ut->refcnt);
1091165916Sjhb		break;
1092165916Sjhb	case UTRACE_PRELOAD_FINISHED:
1093165916Sjhb		printf("RTLD: LD_PRELOAD finished\n");
1094165916Sjhb		break;
1095165916Sjhb	case UTRACE_INIT_CALL:
1096165916Sjhb		printf("RTLD: init %p for %p (%s)\n", ut->mapbase, ut->handle,
1097165916Sjhb		    ut->name);
1098165916Sjhb		break;
1099165916Sjhb	case UTRACE_FINI_CALL:
1100165916Sjhb		printf("RTLD: fini %p for %p (%s)\n", ut->mapbase, ut->handle,
1101165916Sjhb		    ut->name);
1102165916Sjhb		break;
1103165916Sjhb	default:
1104165916Sjhb		p += 4;
1105165916Sjhb		len -= 4;
1106165916Sjhb		printf("RTLD: %d ", len);
1107165916Sjhb		while (len--)
1108165916Sjhb			if (decimal)
1109165916Sjhb				printf(" %d", *p++);
1110165916Sjhb			else
1111165916Sjhb				printf(" %02x", *p++);
1112165916Sjhb		printf("\n");
1113165916Sjhb	}
1114165916Sjhb}
1115165916Sjhb
1116165812Sjhbstruct utrace_malloc {
1117165812Sjhb	void *p;
1118165812Sjhb	size_t s;
1119165812Sjhb	void *r;
1120165812Sjhb};
1121165812Sjhb
1122100824Sdwmalonevoid
1123165812Sjhbktruser_malloc(int len, unsigned char *p)
1124165812Sjhb{
1125165812Sjhb	struct utrace_malloc *ut = (struct utrace_malloc *)p;
1126165812Sjhb
1127199265Scperciva	if (ut->p == (void *)(intptr_t)(-1))
1128199265Scperciva		printf("malloc_init()\n");
1129199265Scperciva	else if (ut->s == 0)
1130199265Scperciva		printf("free(%p)\n", ut->p);
1131199265Scperciva	else if (ut->p == NULL)
1132199265Scperciva		printf("%p = malloc(%zu)\n", ut->r, ut->s);
1133199265Scperciva	else
1134199265Scperciva		printf("%p = realloc(%p, %zu)\n", ut->r, ut->p, ut->s);
1135165812Sjhb}
1136165812Sjhb
1137165812Sjhbvoid
1138100824Sdwmalonektruser(int len, unsigned char *p)
113918400Sphk{
1140165812Sjhb
1141165916Sjhb	if (len >= 8 && bcmp(p, "RTLD", 4) == 0) {
1142165916Sjhb		ktruser_rtld(len, p);
1143165916Sjhb		return;
1144165916Sjhb	}
1145165916Sjhb
1146165812Sjhb	if (len == sizeof(struct utrace_malloc)) {
1147165812Sjhb		ktruser_malloc(len, p);
1148165812Sjhb		return;
1149165812Sjhb	}
1150165812Sjhb
115118470Sphk	(void)printf("%d ", len);
115218470Sphk	while (len--)
1153127402Sphk		if (decimal)
1154127402Sphk			(void)printf(" %d", *p++);
1155127402Sphk		else
1156127402Sphk			(void)printf(" %02x", *p++);
115718400Sphk	(void)printf("\n");
115818400Sphk}
115918400Sphk
1160100824Sdwmalonevoid
1161176471Sdesktrsockaddr(struct sockaddr *sa)
1162176471Sdes{
1163176471Sdes/*
1164176471Sdes TODO: Support additional address families
1165176471Sdes	#include <netnatm/natm.h>
1166176471Sdes	struct sockaddr_natm	*natm;
1167176471Sdes	#include <netsmb/netbios.h>
1168176471Sdes	struct sockaddr_nb	*nb;
1169176471Sdes*/
1170176471Sdes	char addr[64];
1171176471Sdes
1172176471Sdes	/*
1173176471Sdes	 * note: ktrstruct() has already verified that sa points to a
1174176471Sdes	 * buffer at least sizeof(struct sockaddr) bytes long and exactly
1175176471Sdes	 * sa->sa_len bytes long.
1176176471Sdes	 */
1177176471Sdes	printf("struct sockaddr { ");
1178176471Sdes	sockfamilyname(sa->sa_family);
1179176471Sdes	printf(", ");
1180176471Sdes
1181176471Sdes#define check_sockaddr_len(n)					\
1182176471Sdes	if (sa_##n->s##n##_len < sizeof(struct sockaddr_##n)) {	\
1183176471Sdes		printf("invalid");				\
1184176471Sdes		break;						\
1185176471Sdes	}
1186176471Sdes
1187176471Sdes	switch(sa->sa_family) {
1188176471Sdes	case AF_INET: {
1189176471Sdes		struct sockaddr_in	*sa_in;
1190176471Sdes
1191176471Sdes		sa_in = (struct sockaddr_in *)sa;
1192176471Sdes		check_sockaddr_len(in);
1193176471Sdes		inet_ntop(AF_INET, &sa_in->sin_addr, addr, sizeof addr);
1194176471Sdes		printf("%s:%u", addr, ntohs(sa_in->sin_port));
1195176471Sdes		break;
1196176471Sdes	}
1197176471Sdes#ifdef NETATALK
1198176471Sdes	case AF_APPLETALK: {
1199176471Sdes		struct sockaddr_at	*sa_at;
1200176471Sdes		struct netrange		*nr;
1201176471Sdes
1202176471Sdes		sa_at = (struct sockaddr_at *)sa;
1203176471Sdes		check_sockaddr_len(at);
1204176471Sdes		nr = &sa_at->sat_range.r_netrange;
1205176471Sdes		printf("%d.%d, %d-%d, %d", ntohs(sa_at->sat_addr.s_net),
1206176471Sdes			sa_at->sat_addr.s_node, ntohs(nr->nr_firstnet),
1207176471Sdes			ntohs(nr->nr_lastnet), nr->nr_phase);
1208176471Sdes		break;
1209176471Sdes	}
1210176471Sdes#endif
1211176471Sdes	case AF_INET6: {
1212176471Sdes		struct sockaddr_in6	*sa_in6;
1213176471Sdes
1214176471Sdes		sa_in6 = (struct sockaddr_in6 *)sa;
1215176471Sdes		check_sockaddr_len(in6);
1216176471Sdes		inet_ntop(AF_INET6, &sa_in6->sin6_addr, addr, sizeof addr);
1217176471Sdes		printf("[%s]:%u", addr, htons(sa_in6->sin6_port));
1218176471Sdes		break;
1219176471Sdes	}
1220176471Sdes#ifdef IPX
1221176471Sdes	case AF_IPX: {
1222176471Sdes		struct sockaddr_ipx	*sa_ipx;
1223176471Sdes
1224176471Sdes		sa_ipx = (struct sockaddr_ipx *)sa;
1225176471Sdes		check_sockaddr_len(ipx);
1226176471Sdes		/* XXX wish we had ipx_ntop */
1227176471Sdes		printf("%s", ipx_ntoa(sa_ipx->sipx_addr));
1228176471Sdes		break;
1229176471Sdes	}
1230176471Sdes#endif
1231176471Sdes	case AF_UNIX: {
1232176471Sdes		struct sockaddr_un *sa_un;
1233176471Sdes
1234176471Sdes		sa_un = (struct sockaddr_un *)sa;
1235176471Sdes		check_sockaddr_len(un);
1236176471Sdes		printf("%.*s", (int)sizeof(sa_un->sun_path), sa_un->sun_path);
1237176471Sdes		break;
1238176471Sdes	}
1239176471Sdes	default:
1240176471Sdes		printf("unknown address family");
1241176471Sdes	}
1242176471Sdes	printf(" }\n");
1243176471Sdes}
1244176471Sdes
1245176471Sdesvoid
1246176471Sdesktrstat(struct stat *statp)
1247176471Sdes{
1248176471Sdes	char mode[12], timestr[PATH_MAX + 4];
1249176471Sdes	struct passwd *pwd;
1250176471Sdes	struct group  *grp;
1251176471Sdes	struct tm *tm;
1252176471Sdes
1253176471Sdes	/*
1254176471Sdes	 * note: ktrstruct() has already verified that statp points to a
1255176471Sdes	 * buffer exactly sizeof(struct stat) bytes long.
1256176471Sdes	 */
1257176471Sdes	printf("struct stat {");
1258176471Sdes	strmode(statp->st_mode, mode);
1259176471Sdes	printf("dev=%ju, ino=%ju, mode=%s, nlink=%ju, ",
1260176471Sdes		(uintmax_t)statp->st_dev, (uintmax_t)statp->st_ino, mode,
1261176471Sdes		(uintmax_t)statp->st_nlink);
1262176471Sdes	if (resolv == 0 || (pwd = getpwuid(statp->st_uid)) == NULL)
1263176471Sdes		printf("uid=%ju, ", (uintmax_t)statp->st_uid);
1264176471Sdes	else
1265176471Sdes		printf("uid=\"%s\", ", pwd->pw_name);
1266176471Sdes	if (resolv == 0 || (grp = getgrgid(statp->st_gid)) == NULL)
1267176471Sdes		printf("gid=%ju, ", (uintmax_t)statp->st_gid);
1268176471Sdes	else
1269176471Sdes		printf("gid=\"%s\", ", grp->gr_name);
1270176471Sdes	printf("rdev=%ju, ", (uintmax_t)statp->st_rdev);
1271176471Sdes	printf("atime=");
1272176471Sdes	if (resolv == 0)
1273203551Sjh		printf("%jd", (intmax_t)statp->st_atimespec.tv_sec);
1274176471Sdes	else {
1275176471Sdes		tm = localtime(&statp->st_atimespec.tv_sec);
1276176471Sdes		(void)strftime(timestr, sizeof(timestr), TIME_FORMAT, tm);
1277176471Sdes		printf("\"%s\"", timestr);
1278176471Sdes	}
1279176471Sdes	if (statp->st_atimespec.tv_nsec != 0)
1280176471Sdes		printf(".%09ld, ", statp->st_atimespec.tv_nsec);
1281176471Sdes	else
1282176471Sdes		printf(", ");
1283176471Sdes	printf("stime=");
1284176471Sdes	if (resolv == 0)
1285203551Sjh		printf("%jd", (intmax_t)statp->st_mtimespec.tv_sec);
1286176471Sdes	else {
1287176471Sdes		tm = localtime(&statp->st_mtimespec.tv_sec);
1288176471Sdes		(void)strftime(timestr, sizeof(timestr), TIME_FORMAT, tm);
1289176471Sdes		printf("\"%s\"", timestr);
1290176471Sdes	}
1291176471Sdes	if (statp->st_mtimespec.tv_nsec != 0)
1292176471Sdes		printf(".%09ld, ", statp->st_mtimespec.tv_nsec);
1293176471Sdes	else
1294176471Sdes		printf(", ");
1295176471Sdes	printf("ctime=");
1296176471Sdes	if (resolv == 0)
1297203551Sjh		printf("%jd", (intmax_t)statp->st_ctimespec.tv_sec);
1298176471Sdes	else {
1299176471Sdes		tm = localtime(&statp->st_ctimespec.tv_sec);
1300176471Sdes		(void)strftime(timestr, sizeof(timestr), TIME_FORMAT, tm);
1301176471Sdes		printf("\"%s\"", timestr);
1302176471Sdes	}
1303176471Sdes	if (statp->st_ctimespec.tv_nsec != 0)
1304176471Sdes		printf(".%09ld, ", statp->st_ctimespec.tv_nsec);
1305176471Sdes	else
1306176471Sdes		printf(", ");
1307176471Sdes	printf("birthtime=");
1308176471Sdes	if (resolv == 0)
1309203551Sjh		printf("%jd", (intmax_t)statp->st_birthtimespec.tv_sec);
1310176471Sdes	else {
1311176471Sdes		tm = localtime(&statp->st_birthtimespec.tv_sec);
1312176471Sdes		(void)strftime(timestr, sizeof(timestr), TIME_FORMAT, tm);
1313176471Sdes		printf("\"%s\"", timestr);
1314176471Sdes	}
1315176471Sdes	if (statp->st_birthtimespec.tv_nsec != 0)
1316176471Sdes		printf(".%09ld, ", statp->st_birthtimespec.tv_nsec);
1317176471Sdes	else
1318176471Sdes		printf(", ");
1319176471Sdes	printf("size=%jd, blksize=%ju, blocks=%jd, flags=0x%x",
1320176471Sdes		(uintmax_t)statp->st_size, (uintmax_t)statp->st_blksize,
1321176471Sdes		(intmax_t)statp->st_blocks, statp->st_flags);
1322176471Sdes	printf(" }\n");
1323176471Sdes}
1324176471Sdes
1325176471Sdesvoid
1326176471Sdesktrstruct(char *buf, size_t buflen)
1327176471Sdes{
1328176471Sdes	char *name, *data;
1329176471Sdes	size_t namelen, datalen;
1330176471Sdes	int i;
1331176471Sdes
1332176471Sdes	for (name = buf, namelen = 0;
1333176471Sdes	     namelen < buflen && name[namelen] != '\0';
1334176471Sdes	     ++namelen)
1335176471Sdes		/* nothing */;
1336176471Sdes	if (namelen == buflen)
1337176471Sdes		goto invalid;
1338176471Sdes	if (name[namelen] != '\0')
1339176471Sdes		goto invalid;
1340176471Sdes	data = buf + namelen + 1;
1341176471Sdes	datalen = buflen - namelen - 1;
1342176471Sdes	if (datalen == 0)
1343176471Sdes		goto invalid;
1344176471Sdes	/* sanity check */
1345176471Sdes	for (i = 0; i < namelen; ++i)
1346176471Sdes		if (!isalpha((unsigned char)name[i]))
1347176471Sdes			goto invalid;
1348176471Sdes	if (strcmp(name, "stat") == 0) {
1349176471Sdes		if (datalen != sizeof(struct stat))
1350176471Sdes			goto invalid;
1351176471Sdes		ktrstat((struct stat *)data);
1352176471Sdes	} else if (strcmp(name, "sockaddr") == 0) {
1353176471Sdes		if (datalen < sizeof(struct sockaddr) ||
1354176471Sdes		    datalen != ((struct sockaddr *)(data))->sa_len)
1355176471Sdes			goto invalid;
1356176471Sdes		ktrsockaddr((struct sockaddr *)data);
1357176471Sdes	} else {
1358176471Sdes		printf("unknown structure\n");
1359176471Sdes	}
1360176471Sdes	return;
1361176471Sdesinvalid:
1362176471Sdes	printf("invalid record\n");
1363176471Sdes}
1364176471Sdes
1365176471Sdesvoid
1366100824Sdwmaloneusage(void)
13671590Srgrimes{
1368176471Sdes	fprintf(stderr, "usage: kdump [-dEnlHRrsT] [-f trfile] "
1369177856Sru	    "[-m maxdata] [-p pid] [-t trstr]\n");
13701590Srgrimes	exit(1);
13711590Srgrimes}
1372