kdump.c revision 171221
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 171221 2007-07-04 23:32:49Z peter $");
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>
61165916Sjhb#include <dlfcn.h>
6227443Scharnier#include <err.h>
6327443Scharnier#include <locale.h>
641590Srgrimes#include <stdio.h>
651590Srgrimes#include <stdlib.h>
661590Srgrimes#include <string.h>
6727443Scharnier#include <unistd.h>
6827443Scharnier#include <vis.h>
691590Srgrimes#include "ktrace.h"
70158766Snetchild#include "kdump_subr.h"
711590Srgrimes
72100824Sdwmaloneint fread_tail(void *, int, int);
73100824Sdwmalonevoid dumpheader(struct ktr_header *);
74100824Sdwmalonevoid ktrsyscall(struct ktr_syscall *);
75100824Sdwmalonevoid ktrsysret(struct ktr_sysret *);
76100824Sdwmalonevoid ktrnamei(char *, int);
77115759Spetervoid hexdump(char *, int, int);
78115759Spetervoid visdump(char *, int, int);
79100824Sdwmalonevoid ktrgenio(struct ktr_genio *, int);
80100824Sdwmalonevoid ktrpsig(struct ktr_psig *);
81100824Sdwmalonevoid ktrcsw(struct ktr_csw *);
82100824Sdwmalonevoid ktruser(int, unsigned char *);
83100824Sdwmalonevoid usage(void);
84135466Sruconst char *ioctlname(u_long);
85100824Sdwmalone
86152331Srwatsonint timestamp, decimal, fancy = 1, suppressdata, tail, threads, maxdata;
87100824Sdwmaloneconst char *tracefile = DEF_TRACEFILE;
881590Srgrimesstruct ktr_header ktr_header;
891590Srgrimes
901590Srgrimes#define eqs(s1, s2)	(strcmp((s1), (s2)) == 0)
911590Srgrimes
92100824Sdwmaloneint
93100824Sdwmalonemain(int argc, char *argv[])
941590Srgrimes{
951590Srgrimes	int ch, ktrlen, size;
96100824Sdwmalone	void *m;
971590Srgrimes	int trpoints = ALL_POINTS;
98112201Sjhb	int drop_logged;
99115759Speter	pid_t pid = 0;
1001590Srgrimes
10111823Sache	(void) setlocale(LC_CTYPE, "");
10211823Sache
103152331Srwatson	while ((ch = getopt(argc,argv,"f:dElm:np:HRsTt:")) != -1)
1041590Srgrimes		switch((char)ch) {
1051590Srgrimes		case 'f':
1061590Srgrimes			tracefile = optarg;
1071590Srgrimes			break;
1081590Srgrimes		case 'd':
1091590Srgrimes			decimal = 1;
1101590Srgrimes			break;
1111590Srgrimes		case 'l':
1121590Srgrimes			tail = 1;
1131590Srgrimes			break;
1141590Srgrimes		case 'm':
1151590Srgrimes			maxdata = atoi(optarg);
1161590Srgrimes			break;
1171590Srgrimes		case 'n':
1181590Srgrimes			fancy = 0;
1191590Srgrimes			break;
120115759Speter		case 'p':
121115759Speter			pid = atoi(optarg);
122115759Speter			break;
123152331Srwatson		case 's':
124152331Srwatson			suppressdata = 1;
125152331Srwatson			break;
126123187Speter		case 'E':
127123187Speter			timestamp = 3;	/* elapsed timestamp */
128123187Speter			break;
129151930Srwatson		case 'H':
130151930Srwatson			threads = 1;
131151930Srwatson			break;
1321590Srgrimes		case 'R':
1331590Srgrimes			timestamp = 2;	/* relative timestamp */
1341590Srgrimes			break;
1351590Srgrimes		case 'T':
1361590Srgrimes			timestamp = 1;
1371590Srgrimes			break;
1381590Srgrimes		case 't':
1391590Srgrimes			trpoints = getpoints(optarg);
14027443Scharnier			if (trpoints < 0)
14127443Scharnier				errx(1, "unknown trace point in %s", optarg);
1421590Srgrimes			break;
1431590Srgrimes		default:
1441590Srgrimes			usage();
1451590Srgrimes		}
1461590Srgrimes
14719853Sfenner	if (argc > optind)
1481590Srgrimes		usage();
1491590Srgrimes
1501590Srgrimes	m = (void *)malloc(size = 1025);
15127443Scharnier	if (m == NULL)
15227443Scharnier		errx(1, "%s", strerror(ENOMEM));
15327443Scharnier	if (!freopen(tracefile, "r", stdin))
15427443Scharnier		err(1, "%s", tracefile);
155112201Sjhb	drop_logged = 0;
1561590Srgrimes	while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) {
157112201Sjhb		if (ktr_header.ktr_type & KTR_DROP) {
158112201Sjhb			ktr_header.ktr_type &= ~KTR_DROP;
159151930Srwatson			if (!drop_logged && threads) {
160151930Srwatson				(void)printf("%6d %6d %-8.*s Events dropped.\n",
161151930Srwatson				    ktr_header.ktr_pid, ktr_header.ktr_tid >
162151930Srwatson				    0 ? ktr_header.ktr_tid : 0, MAXCOMLEN,
163151930Srwatson				    ktr_header.ktr_comm);
164151930Srwatson				drop_logged = 1;
165151930Srwatson			} else if (!drop_logged) {
166112201Sjhb				(void)printf("%6d %-8.*s Events dropped.\n",
167112201Sjhb				    ktr_header.ktr_pid, MAXCOMLEN,
168112201Sjhb				    ktr_header.ktr_comm);
169112201Sjhb				drop_logged = 1;
170112201Sjhb			}
171112201Sjhb		}
1721590Srgrimes		if (trpoints & (1<<ktr_header.ktr_type))
173115759Speter			if (pid == 0 || ktr_header.ktr_pid == pid)
174115759Speter				dumpheader(&ktr_header);
17527443Scharnier		if ((ktrlen = ktr_header.ktr_len) < 0)
17627443Scharnier			errx(1, "bogus length 0x%x", ktrlen);
1771590Srgrimes		if (ktrlen > size) {
1781590Srgrimes			m = (void *)realloc(m, ktrlen+1);
17927443Scharnier			if (m == NULL)
18027443Scharnier				errx(1, "%s", strerror(ENOMEM));
1811590Srgrimes			size = ktrlen;
1821590Srgrimes		}
18327443Scharnier		if (ktrlen && fread_tail(m, ktrlen, 1) == 0)
18427443Scharnier			errx(1, "data too short");
185115759Speter		if (pid && ktr_header.ktr_pid != pid)
186115759Speter			continue;
1871590Srgrimes		if ((trpoints & (1<<ktr_header.ktr_type)) == 0)
1881590Srgrimes			continue;
189112201Sjhb		drop_logged = 0;
1901590Srgrimes		switch (ktr_header.ktr_type) {
1911590Srgrimes		case KTR_SYSCALL:
1921590Srgrimes			ktrsyscall((struct ktr_syscall *)m);
1931590Srgrimes			break;
1941590Srgrimes		case KTR_SYSRET:
1951590Srgrimes			ktrsysret((struct ktr_sysret *)m);
1961590Srgrimes			break;
1971590Srgrimes		case KTR_NAMEI:
1981590Srgrimes			ktrnamei(m, ktrlen);
1991590Srgrimes			break;
2001590Srgrimes		case KTR_GENIO:
2011590Srgrimes			ktrgenio((struct ktr_genio *)m, ktrlen);
2021590Srgrimes			break;
2031590Srgrimes		case KTR_PSIG:
2041590Srgrimes			ktrpsig((struct ktr_psig *)m);
2051590Srgrimes			break;
2061590Srgrimes		case KTR_CSW:
2071590Srgrimes			ktrcsw((struct ktr_csw *)m);
2081590Srgrimes			break;
20918400Sphk		case KTR_USER:
21018470Sphk			ktruser(ktrlen, m);
21118400Sphk			break;
212112203Sjhb		default:
213112203Sjhb			printf("\n");
214112203Sjhb			break;
2151590Srgrimes		}
2161590Srgrimes		if (tail)
2171590Srgrimes			(void)fflush(stdout);
2181590Srgrimes	}
219100824Sdwmalone	return 0;
2201590Srgrimes}
2211590Srgrimes
222100824Sdwmaloneint
223100824Sdwmalonefread_tail(void *buf, int size, int num)
2241590Srgrimes{
2251590Srgrimes	int i;
2261590Srgrimes
2271590Srgrimes	while ((i = fread(buf, size, num, stdin)) == 0 && tail) {
2281590Srgrimes		(void)sleep(1);
2291590Srgrimes		clearerr(stdin);
2301590Srgrimes	}
2311590Srgrimes	return (i);
2321590Srgrimes}
2331590Srgrimes
234100824Sdwmalonevoid
235100824Sdwmalonedumpheader(struct ktr_header *kth)
2361590Srgrimes{
2371590Srgrimes	static char unknown[64];
2381590Srgrimes	static struct timeval prevtime, temp;
239100824Sdwmalone	const char *type;
2401590Srgrimes
2411590Srgrimes	switch (kth->ktr_type) {
2421590Srgrimes	case KTR_SYSCALL:
2431590Srgrimes		type = "CALL";
2441590Srgrimes		break;
2451590Srgrimes	case KTR_SYSRET:
2461590Srgrimes		type = "RET ";
2471590Srgrimes		break;
2481590Srgrimes	case KTR_NAMEI:
2491590Srgrimes		type = "NAMI";
2501590Srgrimes		break;
2511590Srgrimes	case KTR_GENIO:
2521590Srgrimes		type = "GIO ";
2531590Srgrimes		break;
2541590Srgrimes	case KTR_PSIG:
2551590Srgrimes		type = "PSIG";
2561590Srgrimes		break;
2571590Srgrimes	case KTR_CSW:
2581590Srgrimes		type = "CSW";
2591590Srgrimes		break;
26018400Sphk	case KTR_USER:
26118400Sphk		type = "USER";
26218400Sphk		break;
2631590Srgrimes	default:
2641590Srgrimes		(void)sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type);
2651590Srgrimes		type = unknown;
2661590Srgrimes	}
2671590Srgrimes
268151930Srwatson	/*
269151930Srwatson	 * The ktr_tid field was previously the ktr_buffer field, which held
270151930Srwatson	 * the kernel pointer value for the buffer associated with data
271151930Srwatson	 * following the record header.  It now holds a threadid, but only
272151930Srwatson	 * for trace files after the change.  Older trace files still contain
273151930Srwatson	 * kernel pointers.  Detect this and suppress the results by printing
274151930Srwatson	 * negative tid's as 0.
275151930Srwatson	 */
276151930Srwatson	if (threads)
277151930Srwatson		(void)printf("%6d %6d %-8.*s ", kth->ktr_pid, kth->ktr_tid >
278151930Srwatson		    0 ? kth->ktr_tid : 0, MAXCOMLEN, kth->ktr_comm);
279151930Srwatson	else
280151930Srwatson		(void)printf("%6d %-8.*s ", kth->ktr_pid, MAXCOMLEN,
281151930Srwatson		    kth->ktr_comm);
2821590Srgrimes	if (timestamp) {
283123187Speter		if (timestamp == 3) {
284123187Speter			if (prevtime.tv_sec == 0)
285123187Speter				prevtime = kth->ktr_time;
286123187Speter			timevalsub(&kth->ktr_time, &prevtime);
287123187Speter		}
2881590Srgrimes		if (timestamp == 2) {
2891590Srgrimes			temp = kth->ktr_time;
2901590Srgrimes			timevalsub(&kth->ktr_time, &prevtime);
2911590Srgrimes			prevtime = temp;
2921590Srgrimes		}
2931590Srgrimes		(void)printf("%ld.%06ld ",
2941590Srgrimes		    kth->ktr_time.tv_sec, kth->ktr_time.tv_usec);
2951590Srgrimes	}
2961590Srgrimes	(void)printf("%s  ", type);
2971590Srgrimes}
2981590Srgrimes
2991590Srgrimes#include <sys/syscall.h>
3001590Srgrimes#define KTRACE
3014721Sphk#include <sys/kern/syscalls.c>
3021590Srgrimes#undef KTRACE
3031590Srgrimesint nsyscalls = sizeof (syscallnames) / sizeof (syscallnames[0]);
3041590Srgrimes
305100824Sdwmalonevoid
306100824Sdwmalonektrsyscall(struct ktr_syscall *ktr)
3071590Srgrimes{
308100824Sdwmalone	int narg = ktr->ktr_narg;
309100824Sdwmalone	register_t *ip;
3101590Srgrimes
3111590Srgrimes	if (ktr->ktr_code >= nsyscalls || ktr->ktr_code < 0)
3121590Srgrimes		(void)printf("[%d]", ktr->ktr_code);
3131590Srgrimes	else
3141590Srgrimes		(void)printf("%s", syscallnames[ktr->ktr_code]);
31547957Sdt	ip = &ktr->ktr_args[0];
3161590Srgrimes	if (narg) {
3171590Srgrimes		char c = '(';
3181590Srgrimes		if (fancy) {
319158766Snetchild
320158766Snetchild#define print_number(i,n,c) do {                      \
321158766Snetchild	if (decimal)                                  \
322158766Snetchild		(void)printf("%c%ld", c, (long)*i);   \
323158766Snetchild	else                                          \
324158766Snetchild		(void)printf("%c%#lx", c, (long)*i);  \
325158766Snetchild	i++;                                          \
326158766Snetchild	n--;                                          \
327158766Snetchild	c = ',';                                      \
328158766Snetchild	} while (0);
329158766Snetchild
3301590Srgrimes			if (ktr->ktr_code == SYS_ioctl) {
331100824Sdwmalone				const char *cp;
332158766Snetchild				print_number(ip,narg,c);
3331590Srgrimes				if ((cp = ioctlname(*ip)) != NULL)
3341590Srgrimes					(void)printf(",%s", cp);
3351590Srgrimes				else {
3361590Srgrimes					if (decimal)
33747957Sdt						(void)printf(",%ld", (long)*ip);
3381590Srgrimes					else
33947957Sdt						(void)printf(",%#lx ", (long)*ip);
3401590Srgrimes				}
3411590Srgrimes				c = ',';
3421590Srgrimes				ip++;
3431590Srgrimes				narg--;
3441590Srgrimes			} else if (ktr->ktr_code == SYS_ptrace) {
345168543Semaste				(void)putchar('(');
346168543Semaste				ptraceopname ((int)*ip);
3471590Srgrimes				c = ',';
3481590Srgrimes				ip++;
3491590Srgrimes				narg--;
350158766Snetchild			} else if (ktr->ktr_code == SYS_access ||
351158766Snetchild				   ktr->ktr_code == SYS_eaccess) {
352158766Snetchild				print_number(ip,narg,c);
353158766Snetchild				(void)putchar(',');
354158766Snetchild				accessmodename ((int)*ip);
355158766Snetchild				ip++;
356158766Snetchild				narg--;
357158766Snetchild			} else if (ktr->ktr_code == SYS_open) {
358158766Snetchild				int	flags;
359158766Snetchild				int	mode;
360158766Snetchild				print_number(ip,narg,c);
361158766Snetchild				flags = *ip;
362158766Snetchild				mode = *++ip;
363158766Snetchild				(void)putchar(',');
364158766Snetchild				flagsandmodename (flags, mode, decimal);
365158766Snetchild				ip++;
366158766Snetchild				narg-=2;
367158766Snetchild			} else if (ktr->ktr_code == SYS_wait4) {
368158766Snetchild				print_number(ip,narg,c);
369158766Snetchild				print_number(ip,narg,c);
370158766Snetchild				(void)putchar(',');
371158766Snetchild				wait4optname ((int)*ip);
372158766Snetchild				ip++;
373158766Snetchild				narg--;
374158766Snetchild			} else if (ktr->ktr_code == SYS_chmod ||
375158766Snetchild				   ktr->ktr_code == SYS_fchmod ||
376158766Snetchild				   ktr->ktr_code == SYS_lchmod) {
377158766Snetchild				print_number(ip,narg,c);
378158766Snetchild				(void)putchar(',');
379158766Snetchild				modename ((int)*ip);
380158766Snetchild				ip++;
381158766Snetchild				narg--;
382158766Snetchild			} else if (ktr->ktr_code == SYS_mknod) {
383158766Snetchild				print_number(ip,narg,c);
384158766Snetchild				(void)putchar(',');
385158766Snetchild				modename ((int)*ip);
386158766Snetchild				ip++;
387158766Snetchild				narg--;
388158766Snetchild			} else if (ktr->ktr_code == SYS_getfsstat) {
389158766Snetchild				print_number(ip,narg,c);
390158766Snetchild				print_number(ip,narg,c);
391158766Snetchild				(void)putchar(',');
392158766Snetchild				getfsstatflagsname ((int)*ip);
393158766Snetchild				ip++;
394158766Snetchild				narg--;
395158766Snetchild			} else if (ktr->ktr_code == SYS_mount) {
396158766Snetchild				print_number(ip,narg,c);
397158766Snetchild				print_number(ip,narg,c);
398158766Snetchild				(void)putchar(',');
399158766Snetchild				mountflagsname ((int)*ip);
400158766Snetchild				ip++;
401158766Snetchild				narg--;
402158766Snetchild			} else if (ktr->ktr_code == SYS_unmount) {
403158766Snetchild				print_number(ip,narg,c);
404158766Snetchild				(void)putchar(',');
405158766Snetchild				mountflagsname ((int)*ip);
406158766Snetchild				ip++;
407158766Snetchild				narg--;
408158766Snetchild			} else if (ktr->ktr_code == SYS_recvmsg ||
409158766Snetchild				   ktr->ktr_code == SYS_sendmsg) {
410158766Snetchild				print_number(ip,narg,c);
411158766Snetchild				print_number(ip,narg,c);
412158766Snetchild				(void)putchar(',');
413158766Snetchild				sendrecvflagsname ((int)*ip);
414158766Snetchild				ip++;
415158766Snetchild				narg--;
416158766Snetchild			} else if (ktr->ktr_code == SYS_recvfrom ||
417158766Snetchild				   ktr->ktr_code == SYS_sendto) {
418158766Snetchild				print_number(ip,narg,c);
419158766Snetchild				print_number(ip,narg,c);
420158766Snetchild				print_number(ip,narg,c);
421158766Snetchild				(void)putchar(',');
422158766Snetchild				sendrecvflagsname ((int)*ip);
423158766Snetchild				ip++;
424158766Snetchild				narg--;
425158766Snetchild			} else if (ktr->ktr_code == SYS_chflags ||
426158766Snetchild				   ktr->ktr_code == SYS_fchflags ||
427158766Snetchild				   ktr->ktr_code == SYS_lchflags) {
428158766Snetchild				print_number(ip,narg,c);
429158766Snetchild				(void)putchar(',');
430158766Snetchild				modename((int)*ip);
431158766Snetchild				ip++;
432158766Snetchild				narg--;
433158766Snetchild			} else if (ktr->ktr_code == SYS_kill) {
434158766Snetchild				print_number(ip,narg,c);
435158766Snetchild				(void)putchar(',');
436158766Snetchild				signame((int)*ip);
437158766Snetchild				ip++;
438158766Snetchild				narg--;
439158766Snetchild			} else if (ktr->ktr_code == SYS_reboot) {
440158766Snetchild				(void)putchar('(');
441158766Snetchild				rebootoptname((int)*ip);
442158766Snetchild				ip++;
443158766Snetchild				narg--;
444158766Snetchild			} else if (ktr->ktr_code == SYS_umask) {
445158766Snetchild				(void)putchar('(');
446158766Snetchild				modename((int)*ip);
447158766Snetchild				ip++;
448158766Snetchild				narg--;
449158766Snetchild			} else if (ktr->ktr_code == SYS_msync) {
450158766Snetchild				print_number(ip,narg,c);
451158766Snetchild				print_number(ip,narg,c);
452158766Snetchild				(void)putchar(',');
453158766Snetchild				msyncflagsname((int)*ip);
454158766Snetchild				ip++;
455158766Snetchild				narg--;
456171221Speter#ifdef SYS_freebsd6_mmap
457171221Speter			} else if (ktr->ktr_code == SYS_freebsd6_mmap) {
458171221Speter				print_number(ip,narg,c);
459171221Speter				print_number(ip,narg,c);
460171221Speter				(void)putchar(',');
461171221Speter				mmapprotname ((int)*ip);
462171221Speter				(void)putchar(',');
463171221Speter				ip++;
464171221Speter				narg--;
465171221Speter				mmapflagsname ((int)*ip);
466171221Speter				ip++;
467171221Speter				narg--;
468171221Speter#endif
469158766Snetchild			} else if (ktr->ktr_code == SYS_mmap) {
470158766Snetchild				print_number(ip,narg,c);
471158766Snetchild				print_number(ip,narg,c);
472158766Snetchild				(void)putchar(',');
473158766Snetchild				mmapprotname ((int)*ip);
474158766Snetchild				(void)putchar(',');
475158766Snetchild				ip++;
476158766Snetchild				narg--;
477158766Snetchild				mmapflagsname ((int)*ip);
478158766Snetchild				ip++;
479158766Snetchild				narg--;
480158766Snetchild			} else if (ktr->ktr_code == SYS_mprotect) {
481158766Snetchild				print_number(ip,narg,c);
482158766Snetchild				print_number(ip,narg,c);
483158766Snetchild				(void)putchar(',');
484158766Snetchild				mmapprotname ((int)*ip);
485158766Snetchild				ip++;
486158766Snetchild				narg--;
487158766Snetchild			} else if (ktr->ktr_code == SYS_madvise) {
488158766Snetchild				print_number(ip,narg,c);
489158766Snetchild				print_number(ip,narg,c);
490158766Snetchild				(void)putchar(',');
491158766Snetchild				madvisebehavname((int)*ip);
492158766Snetchild				ip++;
493158766Snetchild				narg--;
494158766Snetchild			} else if (ktr->ktr_code == SYS_setpriority) {
495158766Snetchild				print_number(ip,narg,c);
496158766Snetchild				print_number(ip,narg,c);
497158766Snetchild				(void)putchar(',');
498158766Snetchild				prioname((int)*ip);
499158766Snetchild				ip++;
500158766Snetchild				narg--;
501158766Snetchild			} else if (ktr->ktr_code == SYS_fcntl) {
502158766Snetchild				int cmd;
503158766Snetchild				int arg;
504158766Snetchild				print_number(ip,narg,c);
505158766Snetchild				cmd = *ip;
506158766Snetchild				arg = *++ip;
507158766Snetchild				(void)putchar(',');
508158766Snetchild				fcntlcmdname(cmd, arg, decimal);
509158766Snetchild				ip++;
510158766Snetchild				narg-=2;
511158766Snetchild			} else if (ktr->ktr_code == SYS_socket) {
512165758Srodrigc				int sockdomain;
513158766Snetchild				(void)putchar('(');
514165758Srodrigc				sockdomain=(int)*ip;
515165758Srodrigc				sockdomainname(sockdomain);
516158766Snetchild				ip++;
517158766Snetchild				narg--;
518158766Snetchild				(void)putchar(',');
519158766Snetchild				socktypename((int)*ip);
520158766Snetchild				ip++;
521158766Snetchild				narg--;
522165758Srodrigc				if (sockdomain == PF_INET ||
523165758Srodrigc				    sockdomain == PF_INET6) {
524165758Srodrigc					(void)putchar(',');
525165758Srodrigc					sockipprotoname((int)*ip);
526165758Srodrigc					ip++;
527165758Srodrigc					narg--;
528165758Srodrigc				}
529158766Snetchild				c = ',';
530158766Snetchild			} else if (ktr->ktr_code == SYS_setsockopt ||
531158766Snetchild				   ktr->ktr_code == SYS_getsockopt) {
532158766Snetchild				print_number(ip,narg,c);
533158766Snetchild				(void)putchar(',');
534158766Snetchild				sockoptlevelname((int)*ip, decimal);
535158766Snetchild				ip++;
536158766Snetchild				narg--;
537158766Snetchild				(void)putchar(',');
538158766Snetchild				sockoptname((int)*ip);
539158766Snetchild				ip++;
540158766Snetchild				narg--;
541171221Speter#ifdef SYS_freebsd6_lseek
542171221Speter			} else if (ktr->ktr_code == SYS_freebsd6_lseek) {
543158766Snetchild				print_number(ip,narg,c);
544158766Snetchild				/* Hidden 'pad' argument, not in lseek(2) */
545158766Snetchild				print_number(ip,narg,c);
546158766Snetchild				print_number(ip,narg,c);
547158766Snetchild				(void)putchar(',');
548158766Snetchild				whencename ((int)*ip);
549158766Snetchild				ip++;
550158766Snetchild				narg--;
551171221Speter#endif
552171221Speter			} else if (ktr->ktr_code == SYS_lseek) {
553171221Speter				print_number(ip,narg,c);
554171221Speter				/* Hidden 'pad' argument, not in lseek(2) */
555171221Speter				print_number(ip,narg,c);
556171221Speter				(void)putchar(',');
557171221Speter				whencename ((int)*ip);
558171221Speter				ip++;
559171221Speter				narg--;
560171221Speter
561158766Snetchild			} else if (ktr->ktr_code == SYS_flock) {
562158766Snetchild				print_number(ip,narg,c);
563158766Snetchild				(void)putchar(',');
564158766Snetchild				flockname((int)*ip);
565158766Snetchild				ip++;
566158766Snetchild				narg--;
567158766Snetchild			} else if (ktr->ktr_code == SYS_mkfifo ||
568158766Snetchild				   ktr->ktr_code == SYS_mkdir) {
569158766Snetchild				print_number(ip,narg,c);
570158766Snetchild				(void)putchar(',');
571158766Snetchild				modename((int)*ip);
572158766Snetchild				ip++;
573158766Snetchild				narg--;
574158766Snetchild			} else if (ktr->ktr_code == SYS_shutdown) {
575158766Snetchild				print_number(ip,narg,c);
576158766Snetchild				(void)putchar(',');
577158766Snetchild				shutdownhowname((int)*ip);
578158766Snetchild				ip++;
579158766Snetchild				narg--;
580158766Snetchild			} else if (ktr->ktr_code == SYS_socketpair) {
581158766Snetchild				(void)putchar('(');
582158766Snetchild				sockdomainname((int)*ip);
583158766Snetchild				ip++;
584158766Snetchild				narg--;
585158766Snetchild				(void)putchar(',');
586158766Snetchild				socktypename((int)*ip);
587158766Snetchild				ip++;
588158766Snetchild				narg--;
589158766Snetchild				c = ',';
590158766Snetchild			} else if (ktr->ktr_code == SYS_getrlimit ||
591158766Snetchild				   ktr->ktr_code == SYS_setrlimit) {
592158766Snetchild				(void)putchar('(');
593158766Snetchild				rlimitname((int)*ip);
594158766Snetchild				ip++;
595158766Snetchild				narg--;
596158766Snetchild				c = ',';
597158766Snetchild			} else if (ktr->ktr_code == SYS_quotactl) {
598158766Snetchild				print_number(ip,narg,c);
599158766Snetchild				quotactlname((int)*ip);
600158766Snetchild				ip++;
601158766Snetchild				narg--;
602158766Snetchild				c = ',';
603158766Snetchild			} else if (ktr->ktr_code == SYS_nfssvc) {
604158766Snetchild				(void)putchar('(');
605158766Snetchild				nfssvcname((int)*ip);
606158766Snetchild				ip++;
607158766Snetchild				narg--;
608158766Snetchild				c = ',';
609158766Snetchild			} else if (ktr->ktr_code == SYS_rtprio) {
610158766Snetchild				(void)putchar('(');
611158766Snetchild				rtprioname((int)*ip);
612158766Snetchild				ip++;
613158766Snetchild				narg--;
614158766Snetchild				c = ',';
615158766Snetchild			} else if (ktr->ktr_code == SYS___semctl) {
616158766Snetchild				print_number(ip,narg,c);
617158766Snetchild				print_number(ip,narg,c);
618158766Snetchild				semctlname((int)*ip);
619158766Snetchild				ip++;
620158766Snetchild				narg--;
621158766Snetchild			} else if (ktr->ktr_code == SYS_semget) {
622158766Snetchild				print_number(ip,narg,c);
623158766Snetchild				print_number(ip,narg,c);
624158766Snetchild				semgetname((int)*ip);
625158766Snetchild				ip++;
626158766Snetchild				narg--;
627158766Snetchild			} else if (ktr->ktr_code == SYS_msgctl) {
628158766Snetchild				print_number(ip,narg,c);
629158766Snetchild				shmctlname((int)*ip);
630158766Snetchild				ip++;
631158766Snetchild				narg--;
632158766Snetchild			} else if (ktr->ktr_code == SYS_shmat) {
633158766Snetchild				print_number(ip,narg,c);
634158766Snetchild				print_number(ip,narg,c);
635158766Snetchild				shmatname((int)*ip);
636158766Snetchild				ip++;
637158766Snetchild				narg--;
638158766Snetchild			} else if (ktr->ktr_code == SYS_shmctl) {
639158766Snetchild				print_number(ip,narg,c);
640158766Snetchild				shmctlname((int)*ip);
641158766Snetchild				ip++;
642158766Snetchild				narg--;
643158766Snetchild			} else if (ktr->ktr_code == SYS_minherit) {
644158766Snetchild				print_number(ip,narg,c);
645158766Snetchild				print_number(ip,narg,c);
646158766Snetchild				minheritname((int)*ip);
647158766Snetchild				ip++;
648158766Snetchild				narg--;
649158766Snetchild			} else if (ktr->ktr_code == SYS_rfork) {
650158766Snetchild				(void)putchar('(');
651158766Snetchild				rforkname((int)*ip);
652158766Snetchild				ip++;
653158766Snetchild				narg--;
654158766Snetchild				c = ',';
655158766Snetchild			} else if (ktr->ktr_code == SYS_lio_listio) {
656158766Snetchild				(void)putchar('(');
657158766Snetchild				lio_listioname((int)*ip);
658158766Snetchild				ip++;
659158766Snetchild				narg--;
660158766Snetchild				c = ',';
661158766Snetchild			} else if (ktr->ktr_code == SYS_mlockall) {
662158766Snetchild				(void)putchar('(');
663158766Snetchild				mlockallname((int)*ip);
664158766Snetchild				ip++;
665158766Snetchild				narg--;
666158766Snetchild			} else if (ktr->ktr_code == SYS_sched_setscheduler) {
667158766Snetchild				print_number(ip,narg,c);
668158766Snetchild				schedpolicyname((int)*ip);
669158766Snetchild				ip++;
670158766Snetchild				narg--;
671158766Snetchild			} else if (ktr->ktr_code == SYS_sched_get_priority_max ||
672158766Snetchild				   ktr->ktr_code == SYS_sched_get_priority_min) {
673158766Snetchild				(void)putchar('(');
674158766Snetchild				schedpolicyname((int)*ip);
675158766Snetchild				ip++;
676158766Snetchild				narg--;
677158766Snetchild			} else if (ktr->ktr_code == SYS_sendfile) {
678158766Snetchild				print_number(ip,narg,c);
679158766Snetchild				print_number(ip,narg,c);
680158766Snetchild				print_number(ip,narg,c);
681158766Snetchild				print_number(ip,narg,c);
682158766Snetchild				print_number(ip,narg,c);
683158766Snetchild				print_number(ip,narg,c);
684158766Snetchild				sendfileflagsname((int)*ip);
685158766Snetchild				ip++;
686158766Snetchild				narg--;
687158766Snetchild			} else if (ktr->ktr_code == SYS_kldsym) {
688158766Snetchild				print_number(ip,narg,c);
689158766Snetchild				kldsymcmdname((int)*ip);
690158766Snetchild				ip++;
691158766Snetchild				narg--;
692158766Snetchild			} else if (ktr->ktr_code == SYS_sigprocmask) {
693158766Snetchild				(void)putchar('(');
694158766Snetchild				sigprocmaskhowname((int)*ip);
695158766Snetchild				ip++;
696158766Snetchild				narg--;
697158766Snetchild				c = ',';
698158766Snetchild			} else if (ktr->ktr_code == SYS___acl_get_file ||
699158766Snetchild				   ktr->ktr_code == SYS___acl_set_file ||
700158766Snetchild				   ktr->ktr_code == SYS___acl_get_fd ||
701158766Snetchild				   ktr->ktr_code == SYS___acl_set_fd ||
702158766Snetchild				   ktr->ktr_code == SYS___acl_delete_file ||
703158766Snetchild				   ktr->ktr_code == SYS___acl_delete_fd ||
704158766Snetchild				   ktr->ktr_code == SYS___acl_aclcheck_file ||
705158766Snetchild				   ktr->ktr_code == SYS___acl_aclcheck_fd ||
706158766Snetchild				   ktr->ktr_code == SYS___acl_get_link ||
707158766Snetchild				   ktr->ktr_code == SYS___acl_set_link ||
708158766Snetchild				   ktr->ktr_code == SYS___acl_delete_link ||
709158766Snetchild				   ktr->ktr_code == SYS___acl_aclcheck_link) {
710158766Snetchild				print_number(ip,narg,c);
711158766Snetchild				acltypename((int)*ip);
712158766Snetchild				ip++;
713158766Snetchild				narg--;
714158766Snetchild			} else if (ktr->ktr_code == SYS_sigaction) {
715158766Snetchild				(void)putchar('(');
716158766Snetchild				signame((int)*ip);
717158766Snetchild				ip++;
718158766Snetchild				narg--;
719158766Snetchild				c = ',';
720158766Snetchild			} else if (ktr->ktr_code == SYS_extattrctl) {
721158766Snetchild				print_number(ip,narg,c);
722158766Snetchild				extattrctlname((int)*ip);
723158766Snetchild				ip++;
724158766Snetchild				narg--;
725158766Snetchild			} else if (ktr->ktr_code == SYS_nmount) {
726158766Snetchild				print_number(ip,narg,c);
727158766Snetchild				print_number(ip,narg,c);
728158766Snetchild				(void)putchar(',');
729158766Snetchild				mountflagsname ((int)*ip);
730158766Snetchild				ip++;
731158766Snetchild				narg--;
732158766Snetchild			} else if (ktr->ktr_code == SYS_kse_thr_interrupt) {
733158766Snetchild				print_number(ip,narg,c);
734158766Snetchild				(void)putchar(',');
735158766Snetchild				ksethrcmdname ((int)*ip);
736158766Snetchild				ip++;
737158766Snetchild				narg--;
738158766Snetchild			} else if (ktr->ktr_code == SYS_thr_create) {
739158766Snetchild				print_number(ip,narg,c);
740158766Snetchild				print_number(ip,narg,c);
741158766Snetchild				(void)putchar(',');
742158766Snetchild				thrcreateflagsname ((int)*ip);
743158766Snetchild				ip++;
744158766Snetchild				narg--;
745158766Snetchild			} else if (ktr->ktr_code == SYS_thr_kill) {
746158766Snetchild				print_number(ip,narg,c);
747158766Snetchild				(void)putchar(',');
748158766Snetchild				signame ((int)*ip);
749158766Snetchild				ip++;
750158766Snetchild				narg--;
751158766Snetchild			} else if (ktr->ktr_code == SYS_kldunloadf) {
752158766Snetchild				print_number(ip,narg,c);
753158766Snetchild				(void)putchar(',');
754158766Snetchild				kldunloadfflagsname ((int)*ip);
755158766Snetchild				ip++;
756158766Snetchild				narg--;
7571590Srgrimes			}
7581590Srgrimes		}
7591590Srgrimes		while (narg) {
760158766Snetchild			print_number(ip,narg,c);
7611590Srgrimes		}
7621590Srgrimes		(void)putchar(')');
7631590Srgrimes	}
7641590Srgrimes	(void)putchar('\n');
7651590Srgrimes}
7661590Srgrimes
767100824Sdwmalonevoid
768100824Sdwmalonektrsysret(struct ktr_sysret *ktr)
7691590Srgrimes{
770100824Sdwmalone	register_t ret = ktr->ktr_retval;
771100824Sdwmalone	int error = ktr->ktr_error;
772100824Sdwmalone	int code = ktr->ktr_code;
7731590Srgrimes
7741590Srgrimes	if (code >= nsyscalls || code < 0)
7751590Srgrimes		(void)printf("[%d] ", code);
7761590Srgrimes	else
7771590Srgrimes		(void)printf("%s ", syscallnames[code]);
7781590Srgrimes
7791590Srgrimes	if (error == 0) {
7801590Srgrimes		if (fancy) {
7811590Srgrimes			(void)printf("%d", ret);
7821590Srgrimes			if (ret < 0 || ret > 9)
78347957Sdt				(void)printf("/%#lx", (long)ret);
7841590Srgrimes		} else {
7851590Srgrimes			if (decimal)
78647957Sdt				(void)printf("%ld", (long)ret);
7871590Srgrimes			else
78847957Sdt				(void)printf("%#lx", (long)ret);
7891590Srgrimes		}
7901590Srgrimes	} else if (error == ERESTART)
7911590Srgrimes		(void)printf("RESTART");
7921590Srgrimes	else if (error == EJUSTRETURN)
7931590Srgrimes		(void)printf("JUSTRETURN");
7941590Srgrimes	else {
7951590Srgrimes		(void)printf("-1 errno %d", ktr->ktr_error);
7961590Srgrimes		if (fancy)
7971590Srgrimes			(void)printf(" %s", strerror(ktr->ktr_error));
7981590Srgrimes	}
7991590Srgrimes	(void)putchar('\n');
8001590Srgrimes}
8011590Srgrimes
802100824Sdwmalonevoid
803100824Sdwmalonektrnamei(char *cp, int len)
8041590Srgrimes{
8051590Srgrimes	(void)printf("\"%.*s\"\n", len, cp);
8061590Srgrimes}
8071590Srgrimes
808100824Sdwmalonevoid
809115759Speterhexdump(char *p, int len, int screenwidth)
8101590Srgrimes{
811115759Speter	int n, i;
812115759Speter	int width;
813115759Speter
814115759Speter	width = 0;
815115759Speter	do {
816115759Speter		width += 2;
817115759Speter		i = 13;			/* base offset */
818115759Speter		i += (width / 2) + 1;	/* spaces every second byte */
819115759Speter		i += (width * 2);	/* width of bytes */
820115759Speter		i += 3;			/* "  |" */
821115759Speter		i += width;		/* each byte */
822115759Speter		i += 1;			/* "|" */
823115759Speter	} while (i < screenwidth);
824115759Speter	width -= 2;
825115759Speter
826115759Speter	for (n = 0; n < len; n += width) {
827115759Speter		for (i = n; i < n + width; i++) {
828115759Speter			if ((i % width) == 0) {	/* beginning of line */
829115759Speter				printf("       0x%04x", i);
830115759Speter			}
831115759Speter			if ((i % 2) == 0) {
832115759Speter				printf(" ");
833115759Speter			}
834115759Speter			if (i < len)
835115759Speter				printf("%02x", p[i] & 0xff);
836115759Speter			else
837115759Speter				printf("  ");
838115759Speter		}
839115759Speter		printf("  |");
840115759Speter		for (i = n; i < n + width; i++) {
841115759Speter			if (i >= len)
842115759Speter				break;
843115759Speter			if (p[i] >= ' ' && p[i] <= '~')
844115759Speter				printf("%c", p[i]);
845115759Speter			else
846115759Speter				printf(".");
847115759Speter		}
848115759Speter		printf("|\n");
849115759Speter	}
850115759Speter	if ((i % width) != 0)
851115759Speter		printf("\n");
852115759Speter}
853115759Speter
854115759Spetervoid
855115759Spetervisdump(char *dp, int datalen, int screenwidth)
856115759Speter{
857115759Speter	int col = 0;
858100824Sdwmalone	char *cp;
859100824Sdwmalone	int width;
8601590Srgrimes	char visbuf[5];
8611590Srgrimes
8621590Srgrimes	(void)printf("       \"");
8631590Srgrimes	col = 8;
8641590Srgrimes	for (;datalen > 0; datalen--, dp++) {
8651590Srgrimes		(void) vis(visbuf, *dp, VIS_CSTYLE, *(dp+1));
8661590Srgrimes		cp = visbuf;
8671590Srgrimes		/*
8681590Srgrimes		 * Keep track of printables and
8691590Srgrimes		 * space chars (like fold(1)).
8701590Srgrimes		 */
8711590Srgrimes		if (col == 0) {
8721590Srgrimes			(void)putchar('\t');
8731590Srgrimes			col = 8;
8741590Srgrimes		}
8751590Srgrimes		switch(*cp) {
8761590Srgrimes		case '\n':
8771590Srgrimes			col = 0;
8781590Srgrimes			(void)putchar('\n');
8791590Srgrimes			continue;
8801590Srgrimes		case '\t':
8811590Srgrimes			width = 8 - (col&07);
8821590Srgrimes			break;
8831590Srgrimes		default:
8841590Srgrimes			width = strlen(cp);
8851590Srgrimes		}
8861590Srgrimes		if (col + width > (screenwidth-2)) {
8871590Srgrimes			(void)printf("\\\n\t");
8881590Srgrimes			col = 8;
8891590Srgrimes		}
8901590Srgrimes		col += width;
8911590Srgrimes		do {
8921590Srgrimes			(void)putchar(*cp++);
8931590Srgrimes		} while (*cp);
8941590Srgrimes	}
8951590Srgrimes	if (col == 0)
8961590Srgrimes		(void)printf("       ");
8971590Srgrimes	(void)printf("\"\n");
8981590Srgrimes}
8991590Srgrimes
900115759Spetervoid
901115759Speterktrgenio(struct ktr_genio *ktr, int len)
902115759Speter{
903115759Speter	int datalen = len - sizeof (struct ktr_genio);
904115759Speter	char *dp = (char *)ktr + sizeof (struct ktr_genio);
905115759Speter	static int screenwidth = 0;
906115759Speter	int i, binary;
907115759Speter
908115759Speter	if (screenwidth == 0) {
909115759Speter		struct winsize ws;
910115759Speter
911115759Speter		if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 &&
912115759Speter		    ws.ws_col > 8)
913115759Speter			screenwidth = ws.ws_col;
914115759Speter		else
915115759Speter			screenwidth = 80;
916115759Speter	}
917115759Speter	printf("fd %d %s %d byte%s\n", ktr->ktr_fd,
918115759Speter		ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen,
919115759Speter		datalen == 1 ? "" : "s");
920152331Srwatson	if (suppressdata)
921152331Srwatson		return;
922115759Speter	if (maxdata && datalen > maxdata)
923115759Speter		datalen = maxdata;
924115759Speter
925115759Speter	for (i = 0, binary = 0; i < datalen && binary == 0; i++)  {
926115759Speter		if (dp[i] >= 32 && dp[i] < 127)
927115759Speter			continue;
928115759Speter		if (dp[i] == 10 || dp[i] == 13 || dp[i] == 0 || dp[i] == 9)
929115759Speter			continue;
930115759Speter		binary = 1;
931115759Speter	}
932115759Speter	if (binary)
933115759Speter		hexdump(dp, datalen, screenwidth);
934115759Speter	else
935115759Speter		visdump(dp, datalen, screenwidth);
936115759Speter}
937115759Speter
938100824Sdwmaloneconst char *signames[] = {
9391590Srgrimes	"NULL", "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT",	/*  1 - 6  */
9401590Srgrimes	"EMT", "FPE", "KILL", "BUS", "SEGV", "SYS",		/*  7 - 12 */
9411590Srgrimes	"PIPE", "ALRM",  "TERM", "URG", "STOP", "TSTP",		/* 13 - 18 */
9421590Srgrimes	"CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU",		/* 19 - 24 */
9431590Srgrimes	"XFSZ", "VTALRM", "PROF", "WINCH", "29", "USR1",	/* 25 - 30 */
9441590Srgrimes	"USR2", NULL,						/* 31 - 32 */
9451590Srgrimes};
9461590Srgrimes
947100824Sdwmalonevoid
948100824Sdwmalonektrpsig(struct ktr_psig *psig)
9491590Srgrimes{
950160294Skib	if (psig->signo > 0 && psig->signo < NSIG)
951160296Smaxim		(void)printf("SIG%s ", signames[psig->signo]);
952160294Skib	else
953160296Smaxim		(void)printf("SIG %d ", psig->signo);
9541590Srgrimes	if (psig->action == SIG_DFL)
9551590Srgrimes		(void)printf("SIG_DFL\n");
956100824Sdwmalone	else {
95747957Sdt		(void)printf("caught handler=0x%lx mask=0x%x code=0x%x\n",
958100824Sdwmalone		    (u_long)psig->action, psig->mask.__bits[0], psig->code);
959100824Sdwmalone	}
9601590Srgrimes}
9611590Srgrimes
962100824Sdwmalonevoid
963100824Sdwmalonektrcsw(struct ktr_csw *cs)
9641590Srgrimes{
9651590Srgrimes	(void)printf("%s %s\n", cs->out ? "stop" : "resume",
9661590Srgrimes		cs->user ? "user" : "kernel");
9671590Srgrimes}
9681590Srgrimes
969165916Sjhb#define	UTRACE_DLOPEN_START		1
970165916Sjhb#define	UTRACE_DLOPEN_STOP		2
971165916Sjhb#define	UTRACE_DLCLOSE_START		3
972165916Sjhb#define	UTRACE_DLCLOSE_STOP		4
973165916Sjhb#define	UTRACE_LOAD_OBJECT		5
974165916Sjhb#define	UTRACE_UNLOAD_OBJECT		6
975165916Sjhb#define	UTRACE_ADD_RUNDEP		7
976165916Sjhb#define	UTRACE_PRELOAD_FINISHED		8
977165916Sjhb#define	UTRACE_INIT_CALL		9
978165916Sjhb#define	UTRACE_FINI_CALL		10
979165916Sjhb
980165916Sjhbstruct utrace_rtld {
981165916Sjhb	char sig[4];				/* 'RTLD' */
982165916Sjhb	int event;
983165916Sjhb	void *handle;
984165916Sjhb	void *mapbase;
985165916Sjhb	size_t mapsize;
986165916Sjhb	int refcnt;
987165916Sjhb	char name[MAXPATHLEN];
988165916Sjhb};
989165916Sjhb
990165916Sjhbvoid
991165916Sjhbktruser_rtld(int len, unsigned char *p)
992165916Sjhb{
993165916Sjhb	struct utrace_rtld *ut = (struct utrace_rtld *)p;
994165916Sjhb	void *parent;
995165916Sjhb	int mode;
996165916Sjhb
997165916Sjhb	switch (ut->event) {
998165916Sjhb	case UTRACE_DLOPEN_START:
999165916Sjhb		mode = ut->refcnt;
1000165916Sjhb		printf("dlopen(%s, ", ut->name);
1001165916Sjhb		switch (mode & RTLD_MODEMASK) {
1002165916Sjhb		case RTLD_NOW:
1003165916Sjhb			printf("RTLD_NOW");
1004165916Sjhb			break;
1005165916Sjhb		case RTLD_LAZY:
1006165916Sjhb			printf("RTLD_LAZY");
1007165916Sjhb			break;
1008165916Sjhb		default:
1009165916Sjhb			printf("%#x", mode & RTLD_MODEMASK);
1010165916Sjhb		}
1011165916Sjhb		if (mode & RTLD_GLOBAL)
1012165916Sjhb			printf(" | RTLD_GLOBAL");
1013165916Sjhb		if (mode & RTLD_TRACE)
1014165916Sjhb			printf(" | RTLD_TRACE");
1015165916Sjhb		if (mode & ~(RTLD_MODEMASK | RTLD_GLOBAL | RTLD_TRACE))
1016165916Sjhb			printf(" | %#x", mode &
1017165916Sjhb			    ~(RTLD_MODEMASK | RTLD_GLOBAL | RTLD_TRACE));
1018165916Sjhb		printf(")\n");
1019165916Sjhb		break;
1020165916Sjhb	case UTRACE_DLOPEN_STOP:
1021165916Sjhb		printf("%p = dlopen(%s) ref %d\n", ut->handle, ut->name,
1022165916Sjhb		    ut->refcnt);
1023165916Sjhb		break;
1024165916Sjhb	case UTRACE_DLCLOSE_START:
1025165916Sjhb		printf("dlclose(%p) (%s, %d)\n", ut->handle, ut->name,
1026165916Sjhb		    ut->refcnt);
1027165916Sjhb		break;
1028165916Sjhb	case UTRACE_DLCLOSE_STOP:
1029165916Sjhb		printf("dlclose(%p) finished\n", ut->handle);
1030165916Sjhb		break;
1031165916Sjhb	case UTRACE_LOAD_OBJECT:
1032165916Sjhb		printf("RTLD: loaded   %p @ %p - %p (%s)\n", ut->handle,
1033165916Sjhb		    ut->mapbase, (char *)ut->mapbase + ut->mapsize - 1,
1034165916Sjhb		    ut->name);
1035165916Sjhb		break;
1036165916Sjhb	case UTRACE_UNLOAD_OBJECT:
1037165916Sjhb		printf("RTLD: unloaded %p @ %p - %p (%s)\n", ut->handle,
1038165916Sjhb		    ut->mapbase, (char *)ut->mapbase + ut->mapsize - 1,
1039165916Sjhb		    ut->name);
1040165916Sjhb		break;
1041165916Sjhb	case UTRACE_ADD_RUNDEP:
1042165916Sjhb		parent = ut->mapbase;
1043165916Sjhb		printf("RTLD: %p now depends on %p (%s, %d)\n", parent,
1044165916Sjhb		    ut->handle, ut->name, ut->refcnt);
1045165916Sjhb		break;
1046165916Sjhb	case UTRACE_PRELOAD_FINISHED:
1047165916Sjhb		printf("RTLD: LD_PRELOAD finished\n");
1048165916Sjhb		break;
1049165916Sjhb	case UTRACE_INIT_CALL:
1050165916Sjhb		printf("RTLD: init %p for %p (%s)\n", ut->mapbase, ut->handle,
1051165916Sjhb		    ut->name);
1052165916Sjhb		break;
1053165916Sjhb	case UTRACE_FINI_CALL:
1054165916Sjhb		printf("RTLD: fini %p for %p (%s)\n", ut->mapbase, ut->handle,
1055165916Sjhb		    ut->name);
1056165916Sjhb		break;
1057165916Sjhb	default:
1058165916Sjhb		p += 4;
1059165916Sjhb		len -= 4;
1060165916Sjhb		printf("RTLD: %d ", len);
1061165916Sjhb		while (len--)
1062165916Sjhb			if (decimal)
1063165916Sjhb				printf(" %d", *p++);
1064165916Sjhb			else
1065165916Sjhb				printf(" %02x", *p++);
1066165916Sjhb		printf("\n");
1067165916Sjhb	}
1068165916Sjhb}
1069165916Sjhb
1070165812Sjhbstruct utrace_malloc {
1071165812Sjhb	void *p;
1072165812Sjhb	size_t s;
1073165812Sjhb	void *r;
1074165812Sjhb};
1075165812Sjhb
1076100824Sdwmalonevoid
1077165812Sjhbktruser_malloc(int len, unsigned char *p)
1078165812Sjhb{
1079165812Sjhb	struct utrace_malloc *ut = (struct utrace_malloc *)p;
1080165812Sjhb
1081165812Sjhb	if (ut->p == NULL) {
1082165812Sjhb		if (ut->s == 0 && ut->r == NULL)
1083165812Sjhb			printf("malloc_init()\n");
1084165812Sjhb		else
1085165812Sjhb			printf("%p = malloc(%zu)\n", ut->r, ut->s);
1086165812Sjhb	} else {
1087165812Sjhb		if (ut->s == 0)
1088165812Sjhb			printf("free(%p)\n", ut->p);
1089165812Sjhb		else
1090165812Sjhb			printf("%p = realloc(%p, %zu)\n", ut->r, ut->p, ut->s);
1091165812Sjhb	}
1092165812Sjhb}
1093165812Sjhb
1094165812Sjhbvoid
1095100824Sdwmalonektruser(int len, unsigned char *p)
109618400Sphk{
1097165812Sjhb
1098165916Sjhb	if (len >= 8 && bcmp(p, "RTLD", 4) == 0) {
1099165916Sjhb		ktruser_rtld(len, p);
1100165916Sjhb		return;
1101165916Sjhb	}
1102165916Sjhb
1103165812Sjhb	if (len == sizeof(struct utrace_malloc)) {
1104165812Sjhb		ktruser_malloc(len, p);
1105165812Sjhb		return;
1106165812Sjhb	}
1107165812Sjhb
110818470Sphk	(void)printf("%d ", len);
110918470Sphk	while (len--)
1110127402Sphk		if (decimal)
1111127402Sphk			(void)printf(" %d", *p++);
1112127402Sphk		else
1113127402Sphk			(void)printf(" %02x", *p++);
111418400Sphk	(void)printf("\n");
111518400Sphk}
111618400Sphk
1117100824Sdwmalonevoid
1118100824Sdwmaloneusage(void)
11191590Srgrimes{
11201590Srgrimes	(void)fprintf(stderr,
1121152331Srwatson  "usage: kdump [-dEnlHRsT] [-f trfile] [-m maxdata] [-p pid] [-t [cnisuw]]\n");
11221590Srgrimes	exit(1);
11231590Srgrimes}
1124