xref: /original-bsd/usr.bin/kdump/kdump.c (revision 982436bd)
1 /*
2  * Copyright (c) 1988 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 #ifndef lint
19 char copyright[] =
20 "@(#) Copyright (c) 1988 The Regents of the University of California.\n\
21  All rights reserved.\n";
22 #endif /* not lint */
23 
24 #ifndef lint
25 static char sccsid[] = "@(#)kdump.c	1.5 (Berkeley) 12/21/88";
26 #endif /* not lint */
27 
28 #include "ktrace.h"
29 
30 int timestamp, decimal, fancy = 1, loop, maxdata;
31 char *tracefile = DEF_TRACEFILE;
32 struct ktr_header ktr_header;
33 int size = 1024;	/* initial size of buffer - will grow as needed */
34 
35 #define USAGE	\
36 	"usage: kdump [-dnlT] [-t facilitystring] [-f tracefile] [-m maxdata]\n\
37 	facilities: c = syscalls, n = namei, g = generic-i/o, a = everything\n"
38 
39 #define eqs(s1, s2)	(strcmp((s1), (s2)) == 0)
40 
41 main(argc, argv)
42 	char *argv[];
43 {
44 	extern int optind;
45 	extern char *optarg;
46 	int ch, ktrlen;
47 	register char *m;
48 	int facs = DEF_FACS;
49 
50 	while ((ch = getopt(argc,argv,"t:f:dnlTm:")) != EOF)
51 		switch((char)ch) {
52 			case 't':
53 				facs = getfacs(optarg);
54 				if (facs < 0) {
55 					fprintf(stderr,
56 					     "kdump: unknown facility in %s\n",
57 						optarg);
58 					exit(1);
59 				}
60 				break;
61 			case 'f':
62 				tracefile = optarg;
63 				break;
64 			case 'd':
65 				decimal = 1;
66 				break;
67 			case 'n':
68 				fancy = 0;
69 				break;
70 			case 'l':
71 				loop = 1;
72 				break;
73 			case 'T':
74 				timestamp = 1;
75 				break;
76 			case 'm':
77 				maxdata = atoi(optarg);
78 				break;
79 			default:
80 				fprintf(stderr, USAGE);
81 				exit(1);
82 		}
83 	argv += optind, argc -= optind;
84 
85 	if (argc > 1) {
86 		fprintf(stderr, USAGE);
87 		exit(1);
88 	}
89 	if (!eqs(tracefile, "-")) {
90 		if (freopen(tracefile, "r", stdin) == NULL) {
91 			fprintf(stderr, "kdump: %s: ", tracefile);
92 			perror("");
93 			exit(1);
94 		}
95 	}
96 	m = (char *)malloc(size);
97 	if (m == NULL) {
98 		fprintf(stderr, "kdump: ain't gots no memory\n");
99 		exit(1);
100 	}
101 	while (myfread(&ktr_header, sizeof(struct ktr_header), 1, stdin)) {
102 		if (facs & (1<<ktr_header.ktr_type))
103 			dumpheader(&ktr_header);
104 		if ((ktrlen = ktr_header.ktr_len) > 80000) {	/* XXX */
105 			fprintf(stderr, "kdump: bogus length %d\n",
106 				ktrlen);
107 			exit(1);
108 		}
109 		if (ktrlen > size) {
110 			m = (char *)realloc(m, ktrlen);
111 			if (m == NULL) {
112 				fprintf(stderr,"kdump: ain't gots no memory\n");
113 				exit(1);
114 			}
115 			size = ktrlen;
116 		}
117 		if (myfread(m, ktrlen, 1, stdin) == 0) {
118 			fprintf(stderr, "kdump: out of data\n");
119 			exit(1);
120 		}
121 		if ((facs & (1<<ktr_header.ktr_type)) == 0)
122 			continue;
123 		switch (ktr_header.ktr_type) {
124 		case KTR_SYSCALL:
125 			ktrsyscall((struct ktr_syscall *)m, ktrlen);
126 			break;
127 		case KTR_SYSRET:
128 			ktrsysret((struct ktr_sysret *)m, ktrlen);
129 			break;
130 		case KTR_NAMEI:
131 			ktrnamei(m, ktrlen);
132 			break;
133 		case KTR_GENIO:
134 			ktrgenio((struct ktr_genio *)m, ktrlen);
135 			break;
136 		}
137 		if (loop)
138 			fflush(stdout);
139 	}
140 }
141 
142 myfread(buf, size, num, stream)
143 	char *buf;
144 	FILE *stream;
145 {
146 	int i;
147 again:
148 	if (i = fread(buf, size, num, stream))
149 		return (i);
150 	else {
151 		if (loop) {
152 			sleep(1);
153 			clearerr(stream);
154 			goto again;
155 		} else
156 			return 0;
157 	}
158 }
159 
160 dumpheader(kth)
161 	struct ktr_header *kth;
162 {
163 	static char unknown[64];
164 	char *type;
165 
166 	switch (kth->ktr_type) {
167 	case KTR_SYSCALL:
168 		type = "CALL";
169 		break;
170 	case KTR_SYSRET:
171 		type = "RET ";
172 		break;
173 	case KTR_NAMEI:
174 		type = "NAMI";
175 		break;
176 	case KTR_GENIO:
177 		type = "GIO ";
178 		break;
179 	default:
180 		sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type);
181 		type = unknown;
182 	}
183 
184 	printf("%6d %-8s ",
185 		kth->ktr_pid, kth->ktr_comm);
186 	if (timestamp)
187 		printf("%d.%d ", kth->ktr_time.tv_sec, kth->ktr_time.tv_usec);
188 	printf("%s  ", type);
189 }
190 
191 #include <sys/syscall.h>
192 #define KTRACE
193 #include "/sys/sys/syscalls.c"
194 #undef KTRACE
195 int nsyscalls = sizeof (syscallnames) / sizeof (syscallnames[0]);
196 
197 ktrsyscall(ktr, len)
198 	register struct ktr_syscall *ktr;
199 {
200 	register narg = ktr->ktr_narg;
201 	register int *ip;
202 	char *ioctlname();
203 
204 	if (ktr->ktr_code >= nsyscalls || ktr->ktr_code < 0)
205 		printf("[%d]", ktr->ktr_code);
206 	else
207 		printf("%s", syscallnames[ktr->ktr_code]);
208 	ip = (int *)((char *)ktr + sizeof(struct ktr_syscall));
209 	if (narg) {
210 		char c = '(';
211 		if (fancy && ktr->ktr_code == SYS_ioctl) {
212 			char *cp;
213 			if (decimal)
214 				printf("(%d", *ip);
215 			else
216 				printf("(%#x", *ip);
217 			ip++; narg--;
218 			if ((cp = ioctlname(*ip)) != NULL)
219 				printf(",%s", cp);
220 			else {
221 				if (decimal)
222 					printf(",%d", *ip);
223 				else
224 					printf(",%#x ", *ip);
225 			}
226 			c = ',';
227 			ip++; narg--;
228 		}
229 		while (narg) {
230 			if (decimal)
231 				printf("%c%d", c, *ip);
232 			else
233 				printf("%c%#x", c, *ip);
234 			c = ',';
235 			ip++; narg--;
236 		}
237 		putchar(')');
238 	}
239 	putchar('\n');
240 }
241 
242 ktrsysret(ktr, len)
243 	struct ktr_sysret *ktr;
244 {
245 	extern char *sys_errlist[];
246 	int ret = ktr->ktr_retval;
247 
248 	if (ktr->ktr_code >= nsyscalls || ktr->ktr_code < 0)
249 		printf("[%d] ", ktr->ktr_code);
250 	else
251 		printf("%s ", syscallnames[ktr->ktr_code]);
252 	if (ktr->ktr_error) {
253 		printf("-1 errno %d", ktr->ktr_error);
254 		if (fancy)
255 			printf(" %s", sys_errlist[ktr->ktr_error]);
256 	} else {
257 		if (fancy) {
258 			printf("%d", ret);
259 			if (ret < 0 || ret > 9)
260 				printf(" %#x", ret);
261 		} else {
262 			if (decimal)
263 				printf("%d", ret);
264 			else
265 				printf("%#x", ret);
266 		}
267 	}
268 	putchar('\n');
269 }
270 
271 ktrnamei(cp, len)
272 	char *cp;
273 {
274 	printf("\"%.*s\"\n", len, cp);
275 }
276 
277 ktrgenio(ktr, len)
278 	struct ktr_genio *ktr;
279 {
280 	int datalen = len - sizeof (struct ktr_genio);
281 	char *cp = (char *)ktr + sizeof (struct ktr_genio);
282 	register int col = 0;
283 	register char c;
284 
285 	printf("fd %d %s %d bytes\n", ktr->ktr_fd,
286 		ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen);
287 	if (maxdata && datalen > maxdata)
288 		datalen = maxdata;
289 	for (;datalen > 0; datalen--, cp++) {
290 		c = *cp;
291 
292 		if (col == 0) {
293 			putchar('\t');
294 			col = 1;
295 		}
296 		if (c == '\n' || c == '\t') {
297 			if (c == '\n')
298 				col = 0;
299 			putchar(c);
300 			continue;
301 		}
302 		if (c & 0200) {
303 			putchar('M');
304 			putchar('-');
305 			c &= 0177;
306 		}
307 		if (c < 040 || c == 0177) {
308 			putchar('^');
309 			if (c == 0177)
310 				putchar('?');
311 			else
312 				putchar(c+'@');
313 		} else
314 			putchar(c);
315 	}
316 	if (col != 0)
317 		putchar('\n');
318 }
319