1/*	$OpenBSD: kdump.c,v 1.163 2024/05/18 05:20:22 guenther Exp $	*/
2
3/*-
4 * Copyright (c) 1988, 1993
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 *    may be used to endorse or promote products derived from this software
17 *    without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <sys/time.h>
33#include <sys/signal.h>
34#include <sys/uio.h>
35#include <sys/ktrace.h>
36#include <sys/ioctl.h>
37#include <sys/malloc.h>
38#include <sys/namei.h>
39#include <sys/ptrace.h>
40#include <sys/sem.h>
41#include <sys/shm.h>
42#include <sys/socket.h>
43#include <sys/sysctl.h>
44#include <sys/siginfo.h>
45#include <sys/vmmeter.h>
46#include <sys/tty.h>
47#include <sys/wait.h>
48#define PLEDGENAMES
49#include <sys/pledge.h>
50#undef PLEDGENAMES
51#define _KERNEL
52#include <errno.h>
53#undef _KERNEL
54#include <ddb/db_var.h>
55#include <machine/cpu.h>
56
57#include <ctype.h>
58#include <err.h>
59#include <fcntl.h>
60#include <limits.h>
61#include <netdb.h>
62#include <poll.h>
63#include <signal.h>
64#include <stddef.h>
65#include <stdint.h>
66#include <stdio.h>
67#include <stdlib.h>
68#include <string.h>
69#include <unistd.h>
70#include <vis.h>
71
72#include "ktrace.h"
73#include "kdump.h"
74#include "kdump_subr.h"
75#include "extern.h"
76
77#define nitems(_a)	(sizeof((_a)) / sizeof((_a)[0]))
78
79enum {
80	TIMESTAMP_NONE,
81	TIMESTAMP_ABSOLUTE,
82	TIMESTAMP_RELATIVE,
83	TIMESTAMP_ELAPSED
84} timestamp = TIMESTAMP_NONE;
85
86int decimal, iohex, fancy = 1, maxdata = INT_MAX;
87int needtid, tail, basecol;
88char *tracefile = DEF_TRACEFILE;
89struct ktr_header ktr_header;
90pid_t pid_opt = -1;
91const char *program;
92char* utracefilter;
93
94#define eqs(s1, s2)	(strcmp((s1), (s2)) == 0)
95
96#include <sys/syscall.h>
97
98#define KTRACE
99#define PTRACE
100#define NFSCLIENT
101#define NFSSERVER
102#define SYSVSEM
103#define SYSVMSG
104#define SYSVSHM
105#define ACCOUNTING
106#include <kern/syscalls.c>
107#undef KTRACE
108#undef PTRACE
109#undef NFSCLIENT
110#undef NFSSERVER
111#undef SYSVSEM
112#undef SYSVMSG
113#undef SYSVSHM
114#undef ACCOUNTING
115
116
117static char *ptrace_ops[] = {
118	"PT_TRACE_ME",	"PT_READ_I",	"PT_READ_D",	"PT_READ_U",
119	"PT_WRITE_I",	"PT_WRITE_D",	"PT_WRITE_U",	"PT_CONTINUE",
120	"PT_KILL",	"PT_ATTACH",	"PT_DETACH",	"PT_IO",
121	"PT_SET_EVENT_MASK", "PT_GET_EVENT_MASK", "PT_GET_PROCESS_STATE",
122	"PT_GET_THREAD_FIRST", "PT_GET_THREAD_NEXT",
123};
124
125static int fread_tail(void *, size_t, size_t);
126static void dumpheader(struct ktr_header *);
127static void ktrgenio(struct ktr_genio *, size_t);
128static void ktrnamei(const char *, size_t);
129static void ktrpsig(struct ktr_psig *);
130static void ktrsyscall(struct ktr_syscall *, size_t);
131static const char *kresolvsysctl(int, const int *);
132static void ktrsysret(struct ktr_sysret *, size_t);
133static void ktruser(struct ktr_user *, size_t);
134static void ktrexec(const char*, size_t);
135static void ktrpledge(struct ktr_pledge *, size_t);
136static void ktrpinsyscall(struct ktr_pinsyscall *, size_t);
137static void usage(void);
138static void ioctldecode(int);
139static void ptracedecode(int);
140static void atfd(int);
141static void polltimeout(int);
142static void wait4pid(int);
143static void signame(int);
144static void semctlname(int);
145static void shmctlname(int);
146static void semgetname(int);
147static void flagsandmodename(int);
148static void clockname(int);
149static void sockoptlevelname(int);
150static void ktraceopname(int);
151static void idtypeandid(int);
152
153static int screenwidth;
154
155int
156main(int argc, char *argv[])
157{
158	int ch, silent;
159	size_t ktrlen, size;
160	int trpoints = ALL_POINTS;
161	const char *errstr;
162	void *m;
163
164	if (screenwidth == 0) {
165		struct winsize ws;
166
167		if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 &&
168		    ws.ws_col > 8)
169			screenwidth = ws.ws_col;
170		else
171			screenwidth = 80;
172	}
173
174	while ((ch = getopt(argc, argv, "f:dHlm:nP:p:RTt:u:xX")) != -1)
175		switch (ch) {
176		case 'f':
177			tracefile = optarg;
178			break;
179		case 'd':
180			decimal = 1;
181			break;
182		case 'H':
183			needtid = 1;
184			break;
185		case 'l':
186			tail = 1;
187			break;
188		case 'm':
189			maxdata = strtonum(optarg, 0, INT_MAX, &errstr);
190			if (errstr)
191				errx(1, "-m %s: %s", optarg, errstr);
192			break;
193		case 'n':
194			fancy = 0;
195			break;
196		case 'P':
197			program = optarg;
198			break;
199		case 'p':
200			pid_opt = strtonum(optarg, 1, INT_MAX, &errstr);
201			if (errstr)
202				errx(1, "-p %s: %s", optarg, errstr);
203			break;
204		case 'R':	/* relative timestamp */
205			if (timestamp == TIMESTAMP_ABSOLUTE)
206				timestamp = TIMESTAMP_ELAPSED;
207			else
208				timestamp = TIMESTAMP_RELATIVE;
209			break;
210		case 'T':
211			if (timestamp == TIMESTAMP_RELATIVE)
212				timestamp = TIMESTAMP_ELAPSED;
213			else
214				timestamp = TIMESTAMP_ABSOLUTE;
215			break;
216		case 't':
217			trpoints = getpoints(optarg, DEF_POINTS);
218			if (trpoints < 0)
219				errx(1, "unknown trace point in %s", optarg);
220			utracefilter = NULL;
221			break;
222		case 'u':
223			utracefilter = optarg;
224			trpoints = KTRFAC_USER;
225			break;
226		case 'x':
227			iohex = 1;
228			break;
229		case 'X':
230			iohex = 2;
231			break;
232		default:
233			usage();
234		}
235	if (argc > optind)
236		usage();
237
238	if (strcmp(tracefile, "-") != 0)
239		if (unveil(tracefile, "r") == -1)
240			err(1, "unveil %s", tracefile);
241	if (unveil(_PATH_PROTOCOLS, "r") == -1)
242		err(1, "unveil %s", _PATH_PROTOCOLS);
243	if (pledge("stdio rpath getpw", NULL) == -1)
244		err(1, "pledge");
245
246	m = malloc(size = 1025);
247	if (m == NULL)
248		err(1, NULL);
249	if (strcmp(tracefile, "-") != 0)
250		if (!freopen(tracefile, "r", stdin))
251			err(1, "%s", tracefile);
252
253	if (fread_tail(&ktr_header, sizeof(struct ktr_header), 1) == 0 ||
254	    ktr_header.ktr_type != htobe32(KTR_START))
255		errx(1, "%s: not a dump", tracefile);
256	while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) {
257		silent = 0;
258		if (pid_opt != -1 && pid_opt != ktr_header.ktr_pid)
259			silent = 1;
260		if (program != NULL &&
261		    strcmp(ktr_header.ktr_comm, program) != 0)
262			silent = 1;
263		if (utracefilter == NULL && silent == 0 &&
264		    trpoints & (1<<ktr_header.ktr_type))
265			dumpheader(&ktr_header);
266		ktrlen = ktr_header.ktr_len;
267		if (ktrlen > size) {
268			void *newm;
269
270			if (ktrlen == SIZE_MAX)
271				errx(1, "data too long");
272			newm = realloc(m, ktrlen+1);
273			if (newm == NULL)
274				err(1, "realloc");
275			m = newm;
276			size = ktrlen;
277		}
278		if (ktrlen && fread_tail(m, ktrlen, 1) == 0)
279			errx(1, "data too short");
280		if (silent)
281			continue;
282		if ((trpoints & (1<<ktr_header.ktr_type)) == 0)
283			continue;
284		switch (ktr_header.ktr_type) {
285		case KTR_SYSCALL:
286			ktrsyscall(m, ktrlen);
287			break;
288		case KTR_SYSRET:
289			ktrsysret(m, ktrlen);
290			break;
291		case KTR_NAMEI:
292			ktrnamei(m, ktrlen);
293			break;
294		case KTR_GENIO:
295			ktrgenio(m, ktrlen);
296			break;
297		case KTR_PSIG:
298			ktrpsig(m);
299			break;
300		case KTR_STRUCT:
301			ktrstruct(m, ktrlen);
302			break;
303		case KTR_USER:
304			ktruser(m, ktrlen);
305			break;
306		case KTR_EXECARGS:
307		case KTR_EXECENV:
308			ktrexec(m, ktrlen);
309			break;
310		case KTR_PLEDGE:
311			ktrpledge(m, ktrlen);
312			break;
313		case KTR_PINSYSCALL:
314			ktrpinsyscall(m, ktrlen);
315			break;
316		default:
317			printf("\n");
318			break;
319		}
320		if (tail)
321			(void)fflush(stdout);
322	}
323	exit(0);
324}
325
326static int
327fread_tail(void *buf, size_t size, size_t num)
328{
329	int i;
330
331	while ((i = fread(buf, size, num, stdin)) == 0 && tail) {
332		(void)sleep(1);
333		clearerr(stdin);
334	}
335	return (i);
336}
337
338static void
339dumpheader(struct ktr_header *kth)
340{
341	static struct timespec prevtime;
342	char unknown[64], *type;
343	struct timespec temp;
344
345	switch (kth->ktr_type) {
346	case KTR_SYSCALL:
347		type = "CALL";
348		break;
349	case KTR_SYSRET:
350		type = "RET ";
351		break;
352	case KTR_NAMEI:
353		type = "NAMI";
354		break;
355	case KTR_GENIO:
356		type = "GIO ";
357		break;
358	case KTR_PSIG:
359		type = "PSIG";
360		break;
361	case KTR_STRUCT:
362		type = "STRU";
363		break;
364	case KTR_USER:
365		type = "USER";
366		break;
367	case KTR_EXECARGS:
368		type = "ARGS";
369		break;
370	case KTR_EXECENV:
371		type = "ENV ";
372		break;
373	case KTR_PLEDGE:
374		type = "PLDG";
375		break;
376	case KTR_PINSYSCALL:
377		type = "PINS";
378		break;
379	default:
380		/* htobe32() not guaranteed to work as case label */
381		if (kth->ktr_type == htobe32(KTR_START)) {
382			type = "STRT";
383			break;
384		}
385		(void)snprintf(unknown, sizeof unknown, "UNKNOWN(%u)",
386		    kth->ktr_type);
387		type = unknown;
388	}
389
390	basecol = printf("%6ld", (long)kth->ktr_pid);
391	if (needtid)
392		basecol += printf("/%-7ld", (long)kth->ktr_tid);
393	basecol += printf(" %-8s ", kth->ktr_comm);
394	if (timestamp != TIMESTAMP_NONE) {
395		if (timestamp == TIMESTAMP_ELAPSED) {
396			if (prevtime.tv_sec == 0)
397				prevtime = kth->ktr_time;
398			timespecsub(&kth->ktr_time, &prevtime, &temp);
399		} else if (timestamp == TIMESTAMP_RELATIVE) {
400			timespecsub(&kth->ktr_time, &prevtime, &temp);
401			prevtime = kth->ktr_time;
402		} else
403			temp = kth->ktr_time;
404		basecol += printf("%lld.%06ld ", (long long)temp.tv_sec,
405		    temp.tv_nsec / 1000);
406	}
407	basecol += printf("%s  ", type);
408}
409
410/*
411 * Base Formatters
412 */
413
414/* some syscalls have padding that shouldn't be shown */
415static int
416pad(long arg)
417{
418	/* nothing printed */
419	return (1);
420}
421
422/* a formatter that just saves the argument for the next formatter */
423int arg1;
424static int
425pass_two(long arg)
426{
427	arg1 = (int)arg;
428
429	/* nothing printed */
430	return (1);
431}
432
433static int
434pdeclong(long arg)
435{
436	(void)printf("%ld", arg);
437	return (0);
438}
439
440static int
441pdeculong(long arg)
442{
443	(void)printf("%lu", arg);
444	return (0);
445}
446
447static int
448phexlong(long arg)
449{
450	(void)printf("%#lx", arg);
451	return (0);
452}
453
454static int
455pnonfancy(long arg)
456{
457	if (decimal)
458		(void)printf("%ld", arg);
459	else
460		(void)printf("%#lx", arg);
461	return (0);
462}
463
464static void
465pdecint(int arg)
466{
467	(void)printf("%d", arg);
468}
469
470static void
471pdecuint(int arg)
472{
473	(void)printf("%u", arg);
474}
475
476static void
477phexint(int arg)
478{
479	(void)printf("%#x", arg);
480}
481
482static void
483poctint(int arg)
484{
485	(void)printf("%#o", arg);
486}
487
488
489#ifdef __LP64__
490
491/* on LP64, long long arguments are the same as long arguments */
492#define Phexlonglong	Phexlong
493#define phexll		NULL		/* not actually used on LP64 */
494
495/* no padding before long long arguments, nor at end */
496#define PAD64		0
497#define END64		end_of_args
498
499#else /* __LP64__ */
500
501/* on ILP32, long long arguments are passed as two 32bit args */
502#define Phexlonglong	PASS_LONGLONG, Phexll
503
504static int
505phexll(long arg2)
506{
507	long long val;
508
509#if _BYTE_ORDER == _LITTLE_ENDIAN
510	val = ((long long)arg2 << 32) | ((long long)arg1 & 0xffffffff);
511#else
512	val = ((long long)arg1 << 32) | ((long long)arg2 & 0xffffffff);
513#endif
514
515	if (fancy || !decimal)
516		(void)printf("%#llx", val);
517	else
518		(void)printf("%lld", val);
519	return (0);
520}
521
522/*
523 * Some ILP32 archs naturally align off_t arguments to 8byte boundaries
524 * Get the compiler to tell if this arch is one of them.
525 */
526struct padding_test {
527	int padtest_one;
528	off_t padtest_two;
529};
530#define PAD64	(offsetof(struct padding_test,padtest_two) == 8)
531#define END64	(PAD64 ? PASS_LONGLONG : end_of_args)
532
533#endif /* __LP64__ */
534
535static int (*long_formatters[])(long) = {
536	NULL,
537	pdeclong,
538	pdeculong,
539	phexlong,
540	pass_two,
541	pass_two,
542	phexll,
543	pad,
544	pnonfancy,
545};
546
547static void (*formatters[])(int) = {
548	NULL,
549	pdecint,
550	phexint,
551	poctint,
552	pdecuint,
553	ioctldecode,
554	ptracedecode,
555	atfd,
556	polltimeout,
557	wait4pid,
558	signame,
559	semctlname,
560	shmctlname,
561	semgetname,
562	flagsandmodename,
563	clockname,
564	sockoptlevelname,
565	ktraceopname,
566	fcntlcmdname,
567	modename,
568	flagsname,
569	openflagsname,
570	atflagsname,
571	accessmodename,
572	mmapprotname,
573	mmapflagsname,
574	wait4optname,
575	sendrecvflagsname,
576	mountflagsname,
577	rebootoptname,
578	flockname,
579	sockoptname,
580	sockipprotoname,
581	socktypename,
582	sockflagsname,
583	sockfamilyname,
584	mlockallname,
585	shmatname,
586	whencename,
587	pathconfname,
588	rlimitname,
589	shutdownhowname,
590	prioname,
591	madvisebehavname,
592	msyncflagsname,
593	clocktypename,
594	rusagewho,
595	sigactionflagname,
596	sigprocmaskhowname,
597	minheritname,
598	quotactlname,
599	sigill_name,
600	sigtrap_name,
601	sigemt_name,
602	sigfpe_name,
603	sigbus_name,
604	sigsegv_name,
605	sigchld_name,
606	ktracefacname,
607	itimername,
608	sigset,
609	uidname,
610	gidname,
611	syslogflagname,
612	futexflagname,
613	waitidoptname,
614	idtypeandid,
615};
616
617enum {
618	/* the end of the (known) arguments is recognized by the zero fill */
619	end_of_args	=  0,
620
621	/* negative are the negative of the index into long_formatters[] */
622	Pdeclong	= -1,
623	Pdeculong	= -2,
624	Phexlong	= -3,
625	PASS_TWO	= -4,
626
627/* the remaining long formatters still get called when non-fancy (-n option) */
628#define FMT_IS_NONFANCY(x)	((x) <= PASS_LONGLONG)
629	PASS_LONGLONG	= -5,
630	Phexll		= -6,
631	PAD		= -7,
632	Pnonfancy	= -8,
633
634	/* positive values are the index into formatters[] */
635	Pdecint		= 1,
636	Phexint,
637	Poctint,
638	Pdecuint,
639	Ioctldecode,
640	Ptracedecode,
641	Atfd,
642	Polltimeout,
643	Wait4pid,
644	Signame,
645	Semctlname,
646	Shmctlname,
647	Semgetname,
648	Flagsandmodename,
649	Clockname,
650	Sockoptlevelname,
651	Ktraceopname,
652	Fcntlcmdname,
653	Modename,
654	Flagsname,
655	Openflagsname,
656	Atflagsname,
657	Accessmodename,
658	Mmapprotname,
659	Mmapflagsname,
660	Wait4optname,
661	Sendrecvflagsname,
662	Mountflagsname,
663	Rebootoptname,
664	Flockname,
665	Sockoptname,
666	Sockipprotoname,
667	Socktypename,
668	Sockflagsname,
669	Sockfamilyname,
670	Mlockallname,
671	Shmatname,
672	Whencename,
673	Pathconfname,
674	Rlimitname,
675	Shutdownhowname,
676	Prioname,
677	Madvisebehavname,
678	Msyncflagsname,
679	Clocktypename,
680	Rusagewho,
681	Sigactionflagname,
682	Sigprocmaskhowname,
683	Minheritname,
684	Quotactlname,
685	Sigill_name,
686	Sigtrap_name,
687	Sigemt_name,
688	Sigfpe_name,
689	Sigbus_name,
690	Sigsegv_name,
691	Sigchld_name,
692	Ktracefacname,
693	Itimername,
694	Sigset,
695	Uidname,
696	Gidname,
697	Syslogflagname,
698	Futexflagname,
699	Waitidoptname,
700	Idtypeandid,
701};
702
703#define Pptr		Phexlong
704#define	Psize		Pdeculong	/* size_t for small buffers */
705#define	Pbigsize	Phexlong	/* size_t for I/O buffers */
706#define Pcount		Pdecint		/* int for a count of something */
707#define Pfd		Pdecint
708#define Ppath		Phexlong
709#define Pdev_t		Pdecint
710#define Ppid_t		Pdecint
711#define Ppgid		Pdecint		/* pid or negative pgid */
712#define Poff_t		Phexlonglong
713#define Pmsqid		Pdecint
714#define Pshmid		Pdecint
715#define Psemid		Pdecint
716#define Pkey_t		Pdecint
717#define Pucount		Pdecuint
718#define Chflagsname	Phexlong	/* to be added */
719#define Sockprotoname	Phexlong	/* to be added */
720#define Swapctlname	Phexlong	/* to be added */
721#define Msgflgname	Phexlong	/* to be added */
722
723
724/* includes relevant entries as of syscalls.master rev 1.238 */
725typedef signed char formatter;
726static const formatter scargs[][8] = {
727    [SYS_exit]		= { Pdecint },
728    [SYS_read]		= { Pfd, Pptr, Pbigsize },
729    [SYS_write]		= { Pfd, Pptr, Pbigsize },
730    [SYS_open]		= { Ppath, PASS_TWO, Flagsandmodename },
731    [SYS_close]		= { Pfd },
732    [SYS_getentropy]	= { Pptr, Psize },
733    [SYS___tfork]	= { Pptr, Psize },
734    [SYS_link]		= { Ppath, Ppath },
735    [SYS_unlink]	= { Ppath },
736    [SYS_wait4]		= { Wait4pid, Pptr, Wait4optname },
737    [SYS_chdir]		= { Ppath },
738    [SYS_fchdir]	= { Pfd },
739    [SYS_mknod]		= { Ppath, Modename, Pdev_t },
740    [SYS_chmod]		= { Ppath, Modename },
741    [SYS_chown]		= { Ppath, Uidname, Gidname },
742    [SYS_break]		= { Pptr },
743    [SYS_getrusage]	= { Rusagewho, Pptr },
744    [SYS_mount]		= { Pptr, Ppath, Mountflagsname, Pptr },
745    [SYS_unmount]	= { Ppath, Mountflagsname },
746    [SYS_setuid]	= { Uidname },
747    [SYS_ptrace]	= { Ptracedecode, Ppid_t, Pptr, Pdecint },
748    [SYS_recvmsg]	= { Pfd, Pptr, Sendrecvflagsname },
749    [SYS_sendmsg]	= { Pfd, Pptr, Sendrecvflagsname },
750    [SYS_recvfrom]	= { Pfd, Pptr, Pbigsize, Sendrecvflagsname },
751    [SYS_accept]	= { Pfd, Pptr, Pptr },
752    [SYS_getpeername]	= { Pfd, Pptr, Pptr },
753    [SYS_getsockname]	= { Pfd, Pptr, Pptr },
754    [SYS_access]	= { Ppath, Accessmodename },
755    [SYS_chflags]	= { Ppath, Chflagsname },
756    [SYS_fchflags]	= { Pfd, Chflagsname },
757    [SYS_stat]		= { Ppath, Pptr },
758    [SYS_lstat]		= { Ppath, Pptr },
759    [SYS_dup]		= { Pfd },
760    [SYS_fstatat]	= { Atfd, Ppath, Pptr, Atflagsname },
761    [SYS_profil]	= { Pptr, Pbigsize, Pbigsize, Pdecuint },
762    [SYS_ktrace]	= { Ppath, Ktraceopname, Ktracefacname, Ppgid },
763    [SYS_sigaction]	= { Signame, Pptr, Pptr },
764    [SYS_sigprocmask]	= { Sigprocmaskhowname, Sigset },
765    [SYS_mmap]		= { Pptr, Pbigsize, Mmapprotname, Mmapflagsname, Pfd, Poff_t, END64 },
766    [SYS_setlogin]	= { Pptr },
767    [SYS_acct]		= { Ppath },
768    [SYS_fstat]		= { Pfd, Pptr },
769    [SYS_ioctl]		= { Pfd, Ioctldecode, Pptr },
770    [SYS_reboot]	= { Rebootoptname },
771    [SYS_revoke]	= { Ppath },
772    [SYS_symlink]	= { Ppath, Ppath },
773    [SYS_readlink]	= { Ppath, Pptr, Psize },
774    [SYS_execve]	= { Ppath, Pptr, Pptr },
775    [SYS_umask]		= { Modename },
776    [SYS_chroot]	= { Ppath },
777    [SYS_getfsstat]	= { Pptr, Pbigsize, Mountflagsname },
778    [SYS_statfs]	= { Ppath, Pptr },
779    [SYS_fstatfs]	= { Pfd, Pptr },
780    [SYS_fhstatfs]	= { Pptr, Pptr },
781    [SYS_gettimeofday]	= { Pptr, Pptr },
782    [SYS_settimeofday]	= { Pptr, Pptr },
783    [SYS_setitimer]	= { Itimername, Pptr, Pptr },
784    [SYS_getitimer]	= { Itimername, Pptr },
785    [SYS_select]	= { Pcount, Pptr, Pptr, Pptr, Pptr },
786    [SYS_kevent]	= { Pfd, Pptr, Pcount, Pptr, Pcount, Pptr },
787    [SYS_munmap]	= { Pptr, Pbigsize },
788    [SYS_mprotect]	= { Pptr, Pbigsize, Mmapprotname },
789    [SYS_madvise]	= { Pptr, Pbigsize, Madvisebehavname },
790    [SYS_utimes]	= { Ppath, Pptr },
791    [SYS_futimes]	= { Pfd, Pptr },
792    [SYS_mquery]	= { Pptr, Pbigsize, Mmapprotname, Mmapflagsname, Pfd, Poff_t, END64 },
793    [SYS_getgroups]	= { Pcount, Pptr },
794    [SYS_setgroups]	= { Pcount, Pptr },
795    [SYS_setpgid]	= { Ppid_t, Ppid_t },
796    [SYS_futex]		= { Pptr, Futexflagname, Pcount, Pptr, Pptr },
797    [SYS_utimensat]	= { Atfd, Ppath, Pptr, Atflagsname },
798    [SYS_futimens]	= { Pfd, Pptr },
799    [SYS_kbind]		= { Pptr, Psize, Phexlonglong },
800    [SYS_clock_gettime]	= { Clockname, Pptr },
801    [SYS_clock_settime]	= { Clockname, Pptr },
802    [SYS_clock_getres]	= { Clockname, Pptr },
803    [SYS_dup2]		= { Pfd, Pfd },
804    [SYS_nanosleep]	= { Pptr, Pptr },
805    [SYS_fcntl]		= { Pfd, PASS_TWO, Fcntlcmdname },
806    [SYS_accept4]	= { Pfd, Pptr, Pptr, Sockflagsname },
807    [SYS___thrsleep]	= { Pptr, Clockname, Pptr, Pptr, Pptr },
808    [SYS_fsync]		= { Pfd },
809    [SYS_setpriority]	= { Prioname, Ppid_t, Pdecint },
810    [SYS_socket]	= { Sockfamilyname, Socktypename, Sockprotoname },
811    [SYS_connect]	= { Pfd, Pptr, Pucount },
812    [SYS_getdents]	= { Pfd, Pptr, Pbigsize },
813    [SYS_getpriority]	= { Prioname, Ppid_t },
814    [SYS_pipe2]		= { Pptr, Flagsname },
815    [SYS_dup3]		= { Pfd, Pfd, Flagsname },
816    [SYS_sigreturn]	= { Pptr },
817    [SYS_bind]		= { Pfd, Pptr, Pucount },
818    [SYS_setsockopt]	= { Pfd, PASS_TWO, Sockoptlevelname, Pptr, Pdecint },
819    [SYS_listen]	= { Pfd, Pdecint },
820    [SYS_chflagsat]	= { Atfd, Ppath, Chflagsname, Atflagsname },
821    [SYS_pledge]	= { Pptr, Pptr },
822    [SYS_ppoll]		= { Pptr, Pucount, Pptr, Pptr },
823    [SYS_pselect]	= { Pcount, Pptr, Pptr, Pptr, Pptr, Pptr },
824    [SYS_sigsuspend]	= { Sigset },
825    [SYS_sendsyslog]	= { Pptr, Psize, Syslogflagname },
826    [SYS_unveil]	= { Ppath, Pptr },
827    [SYS___realpath]	= { Ppath, Pptr },
828    [SYS_recvmmsg]	= { Pfd, Pptr, Pucount, Sendrecvflagsname, Pptr },
829    [SYS_sendmmsg]	= { Pfd, Pptr, Pucount, Sendrecvflagsname },
830    [SYS_getsockopt]	= { Pfd, PASS_TWO, Sockoptlevelname, Pptr, Pptr },
831    [SYS_thrkill]	= { Ppid_t, Signame, Pptr },
832    [SYS_readv]		= { Pfd, Pptr, Pcount },
833    [SYS_writev]	= { Pfd, Pptr, Pcount },
834    [SYS_kill]		= { Ppgid, Signame },
835    [SYS_fchown]	= { Pfd, Uidname, Gidname },
836    [SYS_fchmod]	= { Pfd, Modename },
837    [SYS_setreuid]	= { Uidname, Uidname },
838    [SYS_setregid]	= { Gidname, Gidname },
839    [SYS_rename]	= { Ppath, Ppath },
840    [SYS_flock]		= { Pfd, Flockname },
841    [SYS_mkfifo]	= { Ppath, Modename },
842    [SYS_sendto]	= { Pfd, Pptr, Pbigsize, Sendrecvflagsname },
843    [SYS_shutdown]	= { Pfd, Shutdownhowname },
844    [SYS_socketpair]	= { Sockfamilyname, Socktypename, Sockprotoname, Pptr },
845    [SYS_mkdir]		= { Ppath, Modename },
846    [SYS_rmdir]		= { Ppath },
847    [SYS_adjtime]	= { Pptr, Pptr },
848    [SYS_getlogin_r]	= { Pptr, Psize },
849    [SYS_getthrname]	= { Ppid_t, Pptr, Psize },
850    [SYS_setthrname]	= { Ppid_t, Pptr },
851    [SYS_quotactl]	= { Ppath, Quotactlname, Uidname, Pptr },
852    [SYS_ypconnect]	= { Socktypename },
853    [SYS_nfssvc]	= { Phexint, Pptr },
854    [SYS_mimmutable]	= { Pptr, Pbigsize },
855    [SYS_waitid]	= { PASS_TWO, Idtypeandid, Pptr, Waitidoptname },
856    [SYS_getfh]		= { Ppath, Pptr },
857    [SYS___tmpfd]	= { Openflagsname },
858    [SYS_sysarch]	= { Pdecint, Pptr },
859    [SYS_lseek]		= { Pfd, Poff_t, Whencename, END64 },
860    [SYS_truncate]	= { Ppath, Poff_t, END64 },
861    [SYS_ftruncate]	= { Pfd, Poff_t, END64 },
862    [SYS_pread]		= { Pfd, Pptr, Pbigsize, Poff_t, END64 },
863    [SYS_pwrite]        = { Pfd, Pptr, Pbigsize, Poff_t, END64 },
864    [SYS_preadv]	= { Pfd, Pptr, Pcount, Poff_t, END64 },
865    [SYS_pwritev]	= { Pfd, Pptr, Pcount, Poff_t, END64 },
866    [SYS_setgid]	= { Gidname },
867    [SYS_setegid]	= { Gidname },
868    [SYS_seteuid]	= { Uidname },
869    [SYS_pathconfat]	= { Atfd, Ppath, Pathconfname, Atflagsname },
870    [SYS_pathconf]	= { Ppath, Pathconfname },
871    [SYS_fpathconf]	= { Pfd, Pathconfname },
872    [SYS_swapctl]	= { Swapctlname, Pptr, Pdecint },
873    [SYS_getrlimit]	= { Rlimitname, Pptr },
874    [SYS_setrlimit]	= { Rlimitname, Pptr },
875    [SYS_sysctl]	= { Pptr, Pcount, Pptr, Pptr, Pptr, Psize },
876    [SYS_mlock]		= { Pptr, Pbigsize },
877    [SYS_munlock]	= { Pptr, Pbigsize },
878    [SYS_getpgid]	= { Ppid_t },
879    [SYS_utrace]	= { Pptr, Pptr, Psize },
880    [SYS_semget]	= { Pkey_t, Pcount, Semgetname },
881    [SYS_msgget]	= { Pkey_t, Msgflgname },
882    [SYS_msgsnd]	= { Pmsqid, Pptr, Psize, Msgflgname },
883    [SYS_msgrcv]	= { Pmsqid, Pptr, Psize, Pdeclong, Msgflgname },
884    [SYS_shmat]		= { Pshmid, Pptr, Shmatname },
885    [SYS_shmdt]		= { Pptr },
886    [SYS_minherit]	= { Pptr, Pbigsize, Minheritname },
887    [SYS_poll]		= { Pptr, Pucount, Polltimeout },
888    [SYS_lchown]	= { Ppath, Uidname, Gidname },
889    [SYS_getsid]	= { Ppid_t },
890    [SYS_msync]		= { Pptr, Pbigsize, Msyncflagsname },
891    [SYS_pipe]		= { Pptr },
892    [SYS_fhopen]	= { Pptr, Openflagsname },
893    [SYS_kqueue1]	= { Flagsname },
894    [SYS_mlockall]	= { Mlockallname },
895    [SYS_getresuid]	= { Pptr, Pptr, Pptr },
896    [SYS_setresuid]	= { Uidname, Uidname, Uidname },
897    [SYS_getresgid]	= { Pptr, Pptr, Pptr },
898    [SYS_setresgid]	= { Gidname, Gidname, Gidname },
899    [SYS_closefrom]	= { Pfd },
900    [SYS_sigaltstack]	= { Pptr, Pptr },
901    [SYS_shmget]	= { Pkey_t, Pbigsize, Semgetname },
902    [SYS_semop]		= { Psemid, Pptr, Psize },
903    [SYS_fhstat]	= { Pptr, Pptr },
904    [SYS___semctl]	= { Psemid, Pcount, Semctlname, Pptr },
905    [SYS_shmctl]	= { Pshmid, Shmctlname, Pptr },
906    [SYS_msgctl]	= { Pmsqid, Shmctlname, Pptr },
907    [SYS___thrwakeup]	= { Pptr, Pcount },
908    [SYS___threxit]	= { Pptr },
909    [SYS___thrsigdivert] = { Sigset, Pptr, Pptr },
910    [SYS___getcwd]	= { Pptr, Psize },
911    [SYS_adjfreq]	= { Pptr, Pptr },
912    [SYS_setrtable]	= { Pdecint },
913    [SYS_faccessat]	= { Atfd, Ppath, Accessmodename, Atflagsname },
914    [SYS_fchmodat]	= { Atfd, Ppath, Modename, Atflagsname },
915    [SYS_fchownat]	= { Atfd, Ppath, Uidname, Gidname, Atflagsname },
916    [SYS_linkat]	= { Atfd, Ppath, Atfd, Ppath, Atflagsname },
917    [SYS_mkdirat]	= { Atfd, Ppath, Modename },
918    [SYS_mkfifoat]	= { Atfd, Ppath, Modename },
919    [SYS_mknodat]	= { Atfd, Ppath, Modename, Pdev_t },
920    [SYS_openat]	= { Atfd, Ppath, PASS_TWO, Flagsandmodename },
921    [SYS_readlinkat]	= { Atfd, Ppath, Pptr, Psize },
922    [SYS_renameat]	= { Atfd, Ppath, Atfd, Ppath },
923    [SYS_symlinkat]	= { Ppath, Atfd, Ppath },
924    [SYS_unlinkat]	= { Atfd, Ppath, Atflagsname },
925    [SYS___set_tcb]	= { Pptr },
926};
927
928
929static void
930ktrsyscall(struct ktr_syscall *ktr, size_t ktrlen)
931{
932	register_t *ap;
933	int narg, code;
934	char sep;
935
936	if (ktr->ktr_argsize > ktrlen)
937		errx(1, "syscall argument length %d > ktr header length %zu",
938		    ktr->ktr_argsize, ktrlen);
939
940	narg = ktr->ktr_argsize / sizeof(register_t);
941	sep = '\0';
942
943	code = ktr->ktr_code;
944	if (code >= SYS_MAXSYSCALL || code < 0)
945		(void)printf("[%d]", code);
946	else
947		(void)printf("%s", syscallnames[code]);
948	ap = (register_t *)((char *)ktr + sizeof(struct ktr_syscall));
949	(void)putchar('(');
950
951	if (code == SYS_sysctl && fancy) {
952		const char *s;
953		int n, i, *top;
954
955		n = ap[1];
956		if (n > CTL_MAXNAME)
957			n = CTL_MAXNAME;
958		if (n < 0)
959			errx(1, "invalid sysctl length %d", n);
960		if (n > 0) {
961			top = (int *)(ap + 6);
962			printf("%d", top[0]);
963			for (i = 1; i < n; i++)
964				printf(".%d", top[i]);
965			if ((s = kresolvsysctl(0, top)) != NULL) {
966				printf("<%s", s);
967				for (i = 1; i < n; i++) {
968					if ((s = kresolvsysctl(i, top)) != NULL)
969						printf(".%s", s);
970					else
971						printf(".%d", top[i]);
972				}
973				putchar('>');
974			}
975		}
976
977		sep = ',';
978		ap += 2;
979		narg -= 2;
980	} else if (code < nitems(scargs)) {
981		const formatter *fmts = scargs[code];
982		int fmt;
983		int arg = 0;
984
985		while (arg < narg && (fmt = *fmts) != 0) {
986			if (PAD64 && fmt == PASS_LONGLONG && (arg & 1))
987				goto skip;
988			if (sep)
989				putchar(sep);
990			sep = ',';
991			if (!fancy && !FMT_IS_NONFANCY(fmt))
992				fmt = Pnonfancy;
993			if (fmt > 0)
994				formatters[fmt]((int)*ap);
995			else if (long_formatters[-fmt](*ap))
996				sep = '\0';
997			fmts++;
998skip:
999			ap++;
1000			arg++;
1001		}
1002		narg -= arg;
1003	}
1004
1005	while (narg > 0) {
1006		if (sep)
1007			putchar(sep);
1008		if (decimal)
1009			(void)printf("%ld", (long)*ap);
1010		else
1011			(void)printf("%#lx", (long)*ap);
1012		sep = ',';
1013		ap++;
1014		narg--;
1015	}
1016	(void)printf(")\n");
1017}
1018
1019static struct ctlname topname[] = CTL_NAMES;
1020static struct ctlname kernname[] = CTL_KERN_NAMES;
1021static struct ctlname vmname[] = CTL_VM_NAMES;
1022static struct ctlname fsname[] = CTL_FS_NAMES;
1023static struct ctlname netname[] = CTL_NET_NAMES;
1024static struct ctlname hwname[] = CTL_HW_NAMES;
1025static struct ctlname debugname[CTL_DEBUG_MAXID];
1026static struct ctlname kernmallocname[] = CTL_KERN_MALLOC_NAMES;
1027static struct ctlname forkstatname[] = CTL_KERN_FORKSTAT_NAMES;
1028static struct ctlname nchstatsname[] = CTL_KERN_NCHSTATS_NAMES;
1029static struct ctlname kernprocname[] = {
1030	{ NULL },
1031	{ "all" },
1032	{ "pid" },
1033	{ "pgrp" },
1034	{ "session" },
1035	{ "tty" },
1036	{ "uid" },
1037	{ "ruid" },
1038	{ "kthread" },
1039};
1040static struct ctlname ttysname[] = CTL_KERN_TTY_NAMES;
1041static struct ctlname semname[] = CTL_KERN_SEMINFO_NAMES;
1042static struct ctlname shmname[] = CTL_KERN_SHMINFO_NAMES;
1043static struct ctlname watchdogname[] = CTL_KERN_WATCHDOG_NAMES;
1044static struct ctlname tcname[] = CTL_KERN_TIMECOUNTER_NAMES;
1045#ifdef CTL_MACHDEP_NAMES
1046static struct ctlname machdepname[] = CTL_MACHDEP_NAMES;
1047#endif
1048static struct ctlname ddbname[] = CTL_DDB_NAMES;
1049
1050#ifndef nitems
1051#define nitems(_a)    (sizeof((_a)) / sizeof((_a)[0]))
1052#endif
1053
1054#define SETNAME(name) do { names = (name); limit = nitems(name); } while (0)
1055
1056static const char *
1057kresolvsysctl(int depth, const int *top)
1058{
1059	struct ctlname *names;
1060	size_t		limit;
1061	int		idx = top[depth];
1062
1063	names = NULL;
1064
1065	switch (depth) {
1066	case 0:
1067		SETNAME(topname);
1068		break;
1069	case 1:
1070		switch (top[0]) {
1071		case CTL_KERN:
1072			SETNAME(kernname);
1073			break;
1074		case CTL_VM:
1075			SETNAME(vmname);
1076			break;
1077		case CTL_FS:
1078			SETNAME(fsname);
1079			break;
1080		case CTL_NET:
1081			SETNAME(netname);
1082			break;
1083		case CTL_DEBUG:
1084			SETNAME(debugname);
1085			break;
1086		case CTL_HW:
1087			SETNAME(hwname);
1088			break;
1089#ifdef CTL_MACHDEP_NAMES
1090		case CTL_MACHDEP:
1091			SETNAME(machdepname);
1092			break;
1093#endif
1094		case CTL_DDB:
1095			SETNAME(ddbname);
1096			break;
1097		}
1098		break;
1099	case 2:
1100		switch (top[0]) {
1101		case CTL_KERN:
1102			switch (top[1]) {
1103			case KERN_MALLOCSTATS:
1104				SETNAME(kernmallocname);
1105				break;
1106			case KERN_FORKSTAT:
1107				SETNAME(forkstatname);
1108				break;
1109			case KERN_NCHSTATS:
1110				SETNAME(nchstatsname);
1111				break;
1112			case KERN_TTY:
1113				SETNAME(ttysname);
1114				break;
1115			case KERN_SEMINFO:
1116				SETNAME(semname);
1117				break;
1118			case KERN_SHMINFO:
1119				SETNAME(shmname);
1120				break;
1121			case KERN_WATCHDOG:
1122				SETNAME(watchdogname);
1123				break;
1124			case KERN_PROC:
1125				idx++;	/* zero is valid at this level */
1126				SETNAME(kernprocname);
1127				break;
1128			case KERN_TIMECOUNTER:
1129				SETNAME(tcname);
1130				break;
1131			}
1132		}
1133		break;
1134	}
1135	if (names != NULL && idx > 0 && idx < limit)
1136		return (names[idx].ctl_name);
1137	return (NULL);
1138}
1139
1140static void
1141ktrsysret(struct ktr_sysret *ktr, size_t ktrlen)
1142{
1143	register_t ret = 0;
1144	long long retll;
1145	int error = ktr->ktr_error;
1146	int code = ktr->ktr_code;
1147
1148	if (ktrlen < sizeof(*ktr))
1149		errx(1, "sysret length %zu < ktr header length %zu",
1150		    ktrlen, sizeof(*ktr));
1151	ktrlen -= sizeof(*ktr);
1152	if (error == 0) {
1153		if (ktrlen == sizeof(ret)) {
1154			memcpy(&ret, ktr+1, sizeof(ret));
1155			retll = ret;
1156		} else if (ktrlen == sizeof(retll))
1157			memcpy(&retll, ktr+1, sizeof(retll));
1158		else
1159			errx(1, "sysret bogus length %zu", ktrlen);
1160	}
1161
1162	if (code >= SYS_MAXSYSCALL || code < 0)
1163		(void)printf("[%d] ", code);
1164	else
1165		(void)printf("%s ", syscallnames[code]);
1166
1167doerr:
1168	if (error == 0) {
1169		if (fancy) {
1170			switch (code) {
1171			case SYS_lseek:
1172				(void)printf("%lld", retll);
1173				if (retll < 0 || retll > 9)
1174					(void)printf("/%#llx", retll);
1175				break;
1176			case SYS_sigprocmask:
1177			case SYS_sigpending:
1178				sigset(ret);
1179				break;
1180			case SYS___thrsigdivert:
1181				signame(ret);
1182				break;
1183			case SYS_getuid:
1184			case SYS_geteuid:
1185				uidname(ret);
1186				break;
1187			case SYS_getgid:
1188			case SYS_getegid:
1189				gidname(ret);
1190				break;
1191			/* syscalls that return errno values */
1192			case SYS_getlogin_r:
1193			case SYS___thrsleep:
1194			case SYS_getthrname:
1195			case SYS_setthrname:
1196				if ((error = ret) != 0)
1197					goto doerr;
1198				/* FALLTHROUGH */
1199			default:
1200				(void)printf("%ld", (long)ret);
1201				if (ret < 0 || ret > 9)
1202					(void)printf("/%#lx", (long)ret);
1203			}
1204		} else {
1205			if (decimal)
1206				(void)printf("%lld", retll);
1207			else
1208				(void)printf("%#llx", retll);
1209		}
1210	} else if (error == ERESTART)
1211		(void)printf("RESTART");
1212	else if (error == EJUSTRETURN)
1213		(void)printf("JUSTRETURN");
1214	else {
1215		(void)printf("-1 errno %d", error);
1216		if (fancy)
1217			(void)printf(" %s", strerror(error));
1218	}
1219	(void)putchar('\n');
1220}
1221
1222static void
1223ktrnamei(const char *cp, size_t len)
1224{
1225	showbufc(basecol, (unsigned char *)cp, len, VIS_DQ | VIS_TAB | VIS_NL);
1226}
1227
1228void
1229showbufc(int col, unsigned char *dp, size_t datalen, int flags)
1230{
1231	int width;
1232	unsigned char visbuf[5], *cp;
1233
1234	flags |= VIS_CSTYLE;
1235	putchar('"');
1236	col++;
1237	for (; datalen > 0; datalen--, dp++) {
1238		(void)vis(visbuf, *dp, flags, *(dp+1));
1239		cp = visbuf;
1240
1241		/*
1242		 * Keep track of printables and
1243		 * space chars (like fold(1)).
1244		 */
1245		if (col == 0) {
1246			(void)putchar('\t');
1247			col = 8;
1248		}
1249		switch (*cp) {
1250		case '\n':
1251			col = 0;
1252			(void)putchar('\n');
1253			continue;
1254		case '\t':
1255			width = 8 - (col&07);
1256			break;
1257		default:
1258			width = strlen(cp);
1259		}
1260		if (col + width > (screenwidth-2)) {
1261			(void)printf("\\\n\t");
1262			col = 8;
1263		}
1264		col += width;
1265		do {
1266			(void)putchar(*cp++);
1267		} while (*cp);
1268	}
1269	if (col == 0)
1270		(void)printf("       ");
1271	(void)printf("\"\n");
1272}
1273
1274static void
1275showbuf(unsigned char *dp, size_t datalen)
1276{
1277	size_t i, j;
1278	int col = 0, bpl;
1279	unsigned char c;
1280	char visbuf[4 * KTR_USER_MAXLEN + 1];
1281
1282	if (utracefilter != NULL) {
1283		strvisx(visbuf, dp, datalen, VIS_SAFE | VIS_OCTAL);
1284		printf("%s", visbuf);
1285		return;
1286	}
1287	if (iohex == 1) {
1288		putchar('\t');
1289		col = 8;
1290		for (i = 0; i < datalen; i++) {
1291			printf("%02x", dp[i]);
1292			col += 3;
1293			if (i < datalen - 1) {
1294				if (col + 3 > screenwidth) {
1295					printf("\n\t");
1296					col = 8;
1297				} else
1298					putchar(' ');
1299			}
1300		}
1301		putchar('\n');
1302		return;
1303	}
1304	if (iohex == 2) {
1305		bpl = (screenwidth - 13)/4;
1306		if (bpl <= 0)
1307			bpl = 1;
1308		for (i = 0; i < datalen; i += bpl) {
1309			printf("   %04zx:  ", i);
1310			for (j = 0; j < bpl; j++) {
1311				if (i+j >= datalen)
1312					printf("   ");
1313				else
1314					printf("%02x ", dp[i+j]);
1315			}
1316			putchar(' ');
1317			for (j = 0; j < bpl; j++) {
1318				if (i+j >= datalen)
1319					break;
1320				c = dp[i+j];
1321				if (!isprint(c))
1322					c = '.';
1323				putchar(c);
1324			}
1325			putchar('\n');
1326		}
1327		return;
1328	}
1329
1330	(void)printf("       ");
1331	showbufc(7, dp, datalen, 0);
1332}
1333
1334static void
1335ktrgenio(struct ktr_genio *ktr, size_t len)
1336{
1337	unsigned char *dp = (unsigned char *)ktr + sizeof(struct ktr_genio);
1338	size_t datalen;
1339
1340	if (len < sizeof(struct ktr_genio))
1341		errx(1, "invalid ktr genio length %zu", len);
1342
1343	datalen = len - sizeof(struct ktr_genio);
1344
1345	printf("fd %d %s %zu bytes\n", ktr->ktr_fd,
1346		ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen);
1347	if (maxdata == 0)
1348		return;
1349	if (datalen > maxdata)
1350		datalen = maxdata;
1351	if (iohex && !datalen)
1352		return;
1353	showbuf(dp, datalen);
1354}
1355
1356void
1357siginfo(const siginfo_t *si, int show_signo)
1358{
1359	if (show_signo) {
1360		printf("signo=");
1361		signame(si->si_signo);
1362	}
1363	if (si->si_code) {
1364		printf(" code=");
1365		if (!fancy)
1366			printf("<%d>", si->si_code);
1367		else {
1368			switch (si->si_signo) {
1369			case SIGILL:
1370				sigill_name(si->si_code);
1371				break;
1372			case SIGTRAP:
1373				sigtrap_name(si->si_code);
1374				break;
1375			case SIGEMT:
1376				sigemt_name(si->si_code);
1377				break;
1378			case SIGFPE:
1379				sigfpe_name(si->si_code);
1380				break;
1381			case SIGBUS:
1382				sigbus_name(si->si_code);
1383				break;
1384			case SIGSEGV:
1385				sigsegv_name(si->si_code);
1386				break;
1387			case SIGCHLD:
1388				sigchld_name(si->si_code);
1389				break;
1390			default:
1391				printf("<%d>", si->si_code);
1392				break;
1393			}
1394		}
1395	}
1396
1397	switch (si->si_signo) {
1398	case SIGSEGV:
1399	case SIGILL:
1400	case SIGBUS:
1401	case SIGFPE:
1402		printf(" addr=%p trapno=%d", si->si_addr, si->si_trapno);
1403		break;
1404	case SIGCHLD:
1405		if (si->si_code == CLD_EXITED) {
1406			printf(" status=%d", si->si_status);
1407			if (si->si_status < 0 || si->si_status > 9)
1408				(void)printf("/%#x", si->si_status);
1409		} else {
1410			printf(" status=");
1411			signame(si->si_status);
1412		}
1413		printf(" pid=%d uid=", si->si_pid);
1414		uidname(si->si_uid);
1415		break;
1416	default:
1417		break;
1418	}
1419}
1420
1421static void
1422ktrpsig(struct ktr_psig *psig)
1423{
1424	signame(psig->signo);
1425	printf(" ");
1426	if (psig->action == SIG_DFL)
1427		printf("SIG_DFL");
1428	else {
1429		printf("caught handler=0x%lx mask=", (u_long)psig->action);
1430		sigset(psig->mask);
1431	}
1432	siginfo(&psig->si, 0);
1433	putchar('\n');
1434}
1435
1436static void
1437ktruser(struct ktr_user *usr, size_t len)
1438{
1439	if (len < sizeof(struct ktr_user))
1440		errx(1, "invalid ktr user length %zu", len);
1441	len -= sizeof(struct ktr_user);
1442	if (utracefilter == NULL) {
1443		printf("%.*s:", KTR_USER_MAXIDLEN, usr->ktr_id);
1444		printf(" %zu bytes\n", len);
1445		showbuf((unsigned char *)(usr + 1), len);
1446	} else if (strncmp(usr->ktr_id, utracefilter, KTR_USER_MAXIDLEN) == 0)
1447		showbuf((unsigned char *)(usr + 1), len);
1448}
1449
1450static void
1451ktrexec(const char *ptr, size_t len)
1452{
1453	int i, col;
1454	size_t l;
1455
1456	putchar('\n');
1457	i = 0;
1458	while (len > 0) {
1459		l = strnlen(ptr, len);
1460		col = printf("\t[%d] = ", i++);
1461		col += 7;	/* tab expands from 1 to 8 columns */
1462		showbufc(col, (unsigned char *)ptr, l, VIS_DQ|VIS_TAB|VIS_NL);
1463		if (l == len) {
1464			printf("\tunterminated argument\n");
1465			break;
1466		}
1467		len -= l + 1;
1468		ptr += l + 1;
1469	}
1470}
1471
1472static void
1473ktrpledge(struct ktr_pledge *pledge, size_t len)
1474{
1475	const char *name = "";
1476	int i;
1477
1478	if (len < sizeof(struct ktr_pledge))
1479		errx(1, "invalid ktr pledge length %zu", len);
1480
1481	if (pledge->syscall >= SYS_MAXSYSCALL || pledge->syscall < 0)
1482		(void)printf("[%d]", pledge->syscall);
1483	else
1484		(void)printf("%s", syscallnames[pledge->syscall]);
1485	printf(", ");
1486	for (i = 0; pledge->code && pledgenames[i].bits != 0; i++) {
1487		if (pledgenames[i].bits & pledge->code) {
1488			name = pledgenames[i].name;
1489			break;
1490		}
1491	}
1492	printf("\"%s\"", name);
1493	(void)printf(", errno %d", pledge->error);
1494	if (fancy)
1495		(void)printf(" %s", strerror(pledge->error));
1496	printf("\n");
1497}
1498
1499static void
1500ktrpinsyscall(struct ktr_pinsyscall *pinsyscall, size_t len)
1501{
1502	const char *name = "";
1503	int i;
1504
1505	if (len < sizeof(struct ktr_pinsyscall))
1506		errx(1, "invalid ktr pinsyscall length %zu", len);
1507
1508	if (pinsyscall->syscall >= SYS_MAXSYSCALL || pinsyscall->syscall < 0)
1509		(void)printf("[%d]", pinsyscall->syscall);
1510	else
1511		(void)printf("%s", syscallnames[pinsyscall->syscall]);
1512	(void)printf(", addr %lx, errno %d", pinsyscall->addr,
1513	    pinsyscall->error);
1514	(void)printf(", errno %d", pinsyscall->error);
1515	if (fancy)
1516		(void)printf(" %s", strerror(pinsyscall->error));
1517	printf("\n");
1518}
1519
1520static void
1521usage(void)
1522{
1523
1524	extern char *__progname;
1525	fprintf(stderr, "usage: %s "
1526	    "[-dHlnRTXx] [-f file] [-m maxdata] [-P program] [-p pid] "
1527	    "[-t trstr]\n\t[-u label]\n", __progname);
1528	exit(1);
1529}
1530
1531
1532/*
1533 * FORMATTERS
1534 */
1535
1536static void
1537ioctldecode(int cmd)
1538{
1539	char dirbuf[4], *dir = dirbuf;
1540	const char *cp;
1541
1542	if ((cp = ioctlname((unsigned)cmd)) != NULL) {
1543		(void)printf("%s", cp);
1544		return;
1545	}
1546
1547	if (cmd & IOC_IN)
1548		*dir++ = 'W';
1549	if (cmd & IOC_OUT)
1550		*dir++ = 'R';
1551	*dir = '\0';
1552
1553	printf("_IO%s('%c',%d",
1554	    dirbuf, (int)((cmd >> 8) & 0xff), cmd & 0xff);
1555	if ((cmd & IOC_VOID) == 0)
1556		printf(decimal ? ",%u)" : ",%#x)", (cmd >> 16) & 0xff);
1557	else
1558		printf(")");
1559}
1560
1561static void
1562ptracedecode(int request)
1563{
1564	if (request >= 0 && request < nitems(ptrace_ops))
1565		(void)printf("%s", ptrace_ops[request]);
1566	else switch(request) {
1567#ifdef PT_GETFPREGS
1568	case PT_GETFPREGS:
1569		(void)printf("PT_GETFPREGS");
1570		break;
1571#endif
1572	case PT_GETREGS:
1573		(void)printf("PT_GETREGS");
1574		break;
1575#ifdef PT_GETXMMREGS
1576	case PT_GETXMMREGS:
1577		(void)printf("PT_GETXMMREGS");
1578		break;
1579#endif
1580#ifdef PT_SETFPREGS
1581	case PT_SETFPREGS:
1582		(void)printf("PT_SETFPREGS");
1583		break;
1584#endif
1585	case PT_SETREGS:
1586		(void)printf("PT_SETREGS");
1587		break;
1588#ifdef PT_SETXMMREGS
1589	case PT_SETXMMREGS:
1590		(void)printf("PT_SETXMMREGS");
1591		break;
1592#endif
1593#ifdef PT_STEP
1594	case PT_STEP:
1595		(void)printf("PT_STEP");
1596		break;
1597#endif
1598#ifdef PT_WCOOKIE
1599	case PT_WCOOKIE:
1600		(void)printf("PT_WCOOKIE");
1601		break;
1602#endif
1603	default:
1604		pdecint(request);
1605	}
1606}
1607
1608
1609static void
1610atfd(int fd)
1611{
1612	if (fd == AT_FDCWD)
1613		(void)printf("AT_FDCWD");
1614	else
1615		pdecint(fd);
1616}
1617
1618static void
1619polltimeout(int timeout)
1620{
1621	if (timeout == INFTIM)
1622		(void)printf("INFTIM");
1623	else
1624		pdecint(timeout);
1625}
1626
1627static void
1628wait4pid(int pid)
1629{
1630	if (pid == WAIT_ANY)
1631		(void)printf("WAIT_ANY");
1632	else if (pid == WAIT_MYPGRP)
1633		(void)printf("WAIT_MYPGRP");
1634	else
1635		pdecint(pid);		/* ppgid */
1636}
1637
1638static void
1639signame(int sig)
1640{
1641	if (sig > 0 && sig < NSIG)
1642		(void)printf("SIG%s", sys_signame[sig]);
1643	else
1644		(void)printf("SIG %d", sig);
1645}
1646
1647void
1648sigset(int ss)
1649{
1650	int	or = 0;
1651	int	cnt = 0;
1652	int	i;
1653
1654	for (i = 1; i < NSIG; i++)
1655		if (sigismember(&ss, i))
1656			cnt++;
1657	if (cnt > (NSIG-1)/2) {
1658		ss = ~ss;
1659		putchar('~');
1660	}
1661
1662	if (ss == 0) {
1663		(void)printf("0<>");
1664		return;
1665	}
1666
1667	printf("%#x<", ss);
1668	for (i = 1; i < NSIG; i++)
1669		if (sigismember(&ss, i)) {
1670			if (or) putchar('|'); else or=1;
1671			signame(i);
1672		}
1673	printf(">");
1674}
1675
1676static void
1677semctlname(int cmd)
1678{
1679	switch (cmd) {
1680	case GETNCNT:
1681		(void)printf("GETNCNT");
1682		break;
1683	case GETPID:
1684		(void)printf("GETPID");
1685		break;
1686	case GETVAL:
1687		(void)printf("GETVAL");
1688		break;
1689	case GETALL:
1690		(void)printf("GETALL");
1691		break;
1692	case GETZCNT:
1693		(void)printf("GETZCNT");
1694		break;
1695	case SETVAL:
1696		(void)printf("SETVAL");
1697		break;
1698	case SETALL:
1699		(void)printf("SETALL");
1700		break;
1701	case IPC_RMID:
1702		(void)printf("IPC_RMID");
1703		break;
1704	case IPC_SET:
1705		(void)printf("IPC_SET");
1706		break;
1707	case IPC_STAT:
1708		(void)printf("IPC_STAT");
1709		break;
1710	default: /* Should not reach */
1711		(void)printf("<invalid=%d>", cmd);
1712	}
1713}
1714
1715static void
1716shmctlname(int cmd)
1717{
1718	switch (cmd) {
1719	case IPC_RMID:
1720		(void)printf("IPC_RMID");
1721		break;
1722	case IPC_SET:
1723		(void)printf("IPC_SET");
1724		break;
1725	case IPC_STAT:
1726		(void)printf("IPC_STAT");
1727		break;
1728	default: /* Should not reach */
1729		(void)printf("<invalid=%d>", cmd);
1730	}
1731}
1732
1733
1734static void
1735semgetname(int flag)
1736{
1737	int	or = 0;
1738	if_print_or(flag, IPC_CREAT, or);
1739	if_print_or(flag, IPC_EXCL, or);
1740	if_print_or(flag, SEM_R, or);
1741	if_print_or(flag, SEM_A, or);
1742	if_print_or(flag, (SEM_R>>3), or);
1743	if_print_or(flag, (SEM_A>>3), or);
1744	if_print_or(flag, (SEM_R>>6), or);
1745	if_print_or(flag, (SEM_A>>6), or);
1746
1747	if (flag & ~(IPC_CREAT|IPC_EXCL|SEM_R|SEM_A|((SEM_R|SEM_A)>>3)|
1748	    ((SEM_R|SEM_A)>>6)))
1749		printf("<invalid=%#x>", flag);
1750}
1751
1752
1753/*
1754 * Only used by SYS_open and SYS_openat. Unless O_CREAT is set in flags, the
1755 * mode argument is unused (and often bogus and misleading).
1756 */
1757static void
1758flagsandmodename(int mode)
1759{
1760	openflagsname(arg1);
1761	if ((arg1 & O_CREAT) == O_CREAT) {
1762		(void)putchar(',');
1763		modename(mode);
1764	} else if (!fancy)
1765		(void)printf(",<unused>%#o", mode);
1766}
1767
1768static void
1769clockname(int clockid)
1770{
1771	clocktypename(__CLOCK_TYPE(clockid));
1772	if (__CLOCK_PTID(clockid) != 0)
1773		printf("(%d)", __CLOCK_PTID(clockid));
1774}
1775
1776/*
1777 * [g|s]etsockopt's level argument can either be SOL_SOCKET or a value
1778 * referring to a line in /etc/protocols.
1779 */
1780static void
1781sockoptlevelname(int optname)
1782{
1783	struct protoent *pe;
1784
1785	if (arg1 == SOL_SOCKET) {
1786		(void)printf("SOL_SOCKET,");
1787		sockoptname(optname);
1788	} else {
1789		pe = getprotobynumber(arg1);
1790		(void)printf("%u<%s>,%d", arg1,
1791		    pe != NULL ? pe->p_name : "unknown", optname);
1792	}
1793}
1794
1795static void
1796ktraceopname(int ops)
1797{
1798	int invalid = 0;
1799
1800	printf("%#x<", ops);
1801	switch (KTROP(ops)) {
1802	case KTROP_SET:
1803		printf("KTROP_SET");
1804		break;
1805	case KTROP_CLEAR:
1806		printf("KTROP_CLEAR");
1807		break;
1808	case KTROP_CLEARFILE:
1809		printf("KTROP_CLEARFILE");
1810		break;
1811	default:
1812		printf("KTROP(%d)", KTROP(ops));
1813		invalid = 1;
1814		break;
1815	}
1816	if (ops & KTRFLAG_DESCEND) printf("|KTRFLAG_DESCEND");
1817	printf(">");
1818	if (invalid || (ops & ~(KTROP((unsigned)-1) | KTRFLAG_DESCEND)))
1819		(void)printf("<invalid>%d", ops);
1820}
1821
1822static void
1823idtypeandid(int id)
1824{
1825	switch (arg1) {
1826	case P_PID:
1827		printf("P_PID,%d", id);
1828		break;
1829	case P_PGID:
1830		printf("P_PGID,%d", id);
1831		break;
1832	case P_ALL:
1833		printf("P_ALL,<unused>%d", id);
1834		break;
1835	default: /* Should not reach */
1836		printf("<invalid=%d>, <unused>%d", arg1, id);
1837	}
1838}
1839