Annotation of src/usr.bin/kdump/kdump.c, Revision 1.6
1.6 ! deraadt 1: /* $OpenBSD: kdump.c,v 1.5 1996/12/10 15:42:38 deraadt Exp $ */
1.4 deraadt 2:
1.1 deraadt 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. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by the University of
18: * California, Berkeley and its contributors.
19: * 4. Neither the name of the University nor the names of its contributors
20: * may be used to endorse or promote products derived from this software
21: * without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33: * SUCH DAMAGE.
34: */
35:
36: #ifndef lint
37: static char copyright[] =
38: "@(#) Copyright (c) 1988, 1993\n\
39: The Regents of the University of California. All rights reserved.\n";
40: #endif /* not lint */
41:
42: #ifndef lint
43: #if 0
44: static char sccsid[] = "@(#)kdump.c 8.4 (Berkeley) 4/28/95";
45: #endif
1.6 ! deraadt 46: static char *rcsid = "$OpenBSD: kdump.c,v 1.5 1996/12/10 15:42:38 deraadt Exp $";
1.1 deraadt 47: #endif /* not lint */
48:
49: #include <sys/param.h>
50: #include <sys/errno.h>
51: #include <sys/time.h>
52: #include <sys/uio.h>
53: #include <sys/ktrace.h>
54: #include <sys/ioctl.h>
55: #include <sys/ptrace.h>
56: #define _KERNEL
57: #include <sys/errno.h>
58: #undef _KERNEL
59:
60: #include <err.h>
61: #include <signal.h>
62: #include <stdio.h>
63: #include <stdlib.h>
64: #include <string.h>
65: #include <unistd.h>
66: #include <vis.h>
67:
68: #include "ktrace.h"
69:
70: int timestamp, decimal, fancy = 1, tail, maxdata;
71: char *tracefile = DEF_TRACEFILE;
72: struct ktr_header ktr_header;
73:
74: #define eqs(s1, s2) (strcmp((s1), (s2)) == 0)
75:
76: #include <sys/syscall.h>
77:
78: #include "../../sys/compat/hpux/hpux_syscall.h"
79: #include "../../sys/compat/ibcs2/ibcs2_syscall.h"
80: #include "../../sys/compat/linux/linux_syscall.h"
81: #include "../../sys/compat/osf1/osf1_syscall.h"
82: #include "../../sys/compat/sunos/sunos_syscall.h"
83: #include "../../sys/compat/svr4/svr4_syscall.h"
84: #include "../../sys/compat/ultrix/ultrix_syscall.h"
85:
86: #define KTRACE
87: #include "../../sys/kern/syscalls.c"
88:
89: #include "../../sys/compat/hpux/hpux_syscalls.c"
90: #include "../../sys/compat/ibcs2/ibcs2_syscalls.c"
91: #include "../../sys/compat/linux/linux_syscalls.c"
92: #include "../../sys/compat/osf1/osf1_syscalls.c"
93: #include "../../sys/compat/sunos/sunos_syscalls.c"
94: #include "../../sys/compat/svr4/svr4_syscalls.c"
95: #include "../../sys/compat/ultrix/ultrix_syscalls.c"
96: #undef KTRACE
97:
98: struct emulation {
99: char *name; /* Emulation name */
100: char **sysnames; /* Array of system call names */
101: int nsysnames; /* Number of */
102: };
103:
104: static struct emulation emulations[] = {
1.3 deraadt 105: { "native", syscallnames, SYS_MAXSYSCALL },
1.1 deraadt 106: { "hpux", hpux_syscallnames, HPUX_SYS_MAXSYSCALL },
107: { "ibcs2", ibcs2_syscallnames, IBCS2_SYS_MAXSYSCALL },
108: { "linux", linux_syscallnames, LINUX_SYS_MAXSYSCALL },
109: { "osf1", osf1_syscallnames, OSF1_SYS_MAXSYSCALL },
110: { "sunos", sunos_syscallnames, SUNOS_SYS_MAXSYSCALL },
111: { "svr4", svr4_syscallnames, SVR4_SYS_MAXSYSCALL },
112: { "ultrix", ultrix_syscallnames, ULTRIX_SYS_MAXSYSCALL },
113: { NULL, NULL, NULL }
114: };
115:
116: struct emulation *current;
117:
118:
119: static char *ptrace_ops[] = {
120: "PT_TRACE_ME", "PT_READ_I", "PT_READ_D", "PT_READ_U",
121: "PT_WRITE_I", "PT_WRITE_D", "PT_WRITE_U", "PT_CONTINUE",
122: "PT_KILL", "PT_ATTACH", "PT_DETACH",
123: };
124:
125: int
126: main(argc, argv)
127: int argc;
128: char *argv[];
129: {
130: int ch, ktrlen, size;
131: register void *m;
132: int trpoints = ALL_POINTS;
133:
1.3 deraadt 134: current = &emulations[0]; /* native */
1.1 deraadt 135:
136: while ((ch = getopt(argc, argv, "e:f:dlm:nRTt:")) != -1)
137: switch (ch) {
138: case 'e':
139: setemul(optarg);
140: break;
141: case 'f':
142: tracefile = optarg;
143: break;
144: case 'd':
145: decimal = 1;
146: break;
147: case 'l':
148: tail = 1;
149: break;
150: case 'm':
151: maxdata = atoi(optarg);
152: break;
153: case 'n':
154: fancy = 0;
155: break;
156: case 'R':
157: timestamp = 2; /* relative timestamp */
158: break;
159: case 'T':
160: timestamp = 1;
161: break;
162: case 't':
163: trpoints = getpoints(optarg);
164: if (trpoints < 0)
165: errx(1, "unknown trace point in %s", optarg);
166: break;
167: default:
168: usage();
169: }
1.5 deraadt 170: if (argc > optind)
1.1 deraadt 171: usage();
172:
173: m = (void *)malloc(size = 1025);
174: if (m == NULL)
175: errx(1, "%s", strerror(ENOMEM));
176: if (!freopen(tracefile, "r", stdin))
177: err(1, "%s", tracefile);
178: while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) {
179: if (trpoints & (1<<ktr_header.ktr_type))
180: dumpheader(&ktr_header);
181: if ((ktrlen = ktr_header.ktr_len) < 0)
182: errx(1, "bogus length 0x%x", ktrlen);
183: if (ktrlen > size) {
184: m = (void *)realloc(m, ktrlen+1);
185: if (m == NULL)
186: errx(1, "%s", strerror(ENOMEM));
187: size = ktrlen;
188: }
189: if (ktrlen && fread_tail(m, ktrlen, 1) == 0)
190: errx(1, "data too short");
191: if ((trpoints & (1<<ktr_header.ktr_type)) == 0)
192: continue;
193: switch (ktr_header.ktr_type) {
194: case KTR_SYSCALL:
195: ktrsyscall((struct ktr_syscall *)m);
196: break;
197: case KTR_SYSRET:
198: ktrsysret((struct ktr_sysret *)m);
199: break;
200: case KTR_NAMEI:
201: ktrnamei(m, ktrlen);
202: break;
203: case KTR_GENIO:
204: ktrgenio((struct ktr_genio *)m, ktrlen);
205: break;
206: case KTR_PSIG:
207: ktrpsig((struct ktr_psig *)m);
208: break;
209: case KTR_CSW:
210: ktrcsw((struct ktr_csw *)m);
211: break;
212: case KTR_EMUL:
213: ktremul(m, ktrlen);
214: break;
215: }
216: if (tail)
217: (void)fflush(stdout);
218: }
219: }
220:
221: fread_tail(buf, size, num)
222: char *buf;
223: int num, size;
224: {
225: int i;
226:
227: while ((i = fread(buf, size, num, stdin)) == 0 && tail) {
228: (void)sleep(1);
229: clearerr(stdin);
230: }
231: return (i);
232: }
233:
234: dumpheader(kth)
235: struct ktr_header *kth;
236: {
237: char unknown[64], *type;
238: static struct timeval prevtime;
239: struct timeval temp;
240:
241: switch (kth->ktr_type) {
242: case KTR_SYSCALL:
243: type = "CALL";
244: break;
245: case KTR_SYSRET:
246: type = "RET ";
247: break;
248: case KTR_NAMEI:
249: type = "NAMI";
250: break;
251: case KTR_GENIO:
252: type = "GIO ";
253: break;
254: case KTR_PSIG:
255: type = "PSIG";
256: break;
257: case KTR_CSW:
258: type = "CSW";
259: break;
260: case KTR_EMUL:
261: type = "EMUL";
262: break;
263: default:
264: (void)sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type);
265: type = unknown;
266: }
267:
268: (void)printf("%6d %-8.*s ", kth->ktr_pid, MAXCOMLEN, kth->ktr_comm);
269: if (timestamp) {
270: if (timestamp == 2) {
271: timersub(&kth->ktr_time, &prevtime, &temp);
272: prevtime = kth->ktr_time;
273: } else
274: temp = kth->ktr_time;
275: (void)printf("%ld.%06ld ", temp.tv_sec, temp.tv_usec);
276: }
277: (void)printf("%s ", type);
278: }
279:
1.2 deraadt 280: void
281: ioctldecode(cmd)
282: u_long cmd;
283: {
284: char dirbuf[4], *dir = dirbuf;
285:
1.6 ! deraadt 286: if (cmd & IOC_IN)
! 287: *dir++ = 'W';
1.2 deraadt 288: if (cmd & IOC_OUT)
289: *dir++ = 'R';
290: *dir = '\0';
291:
292: printf(decimal ? ",_IO%s('%c',%ld" : ",_IO%s('%c',%#lx",
293: dirbuf, (cmd >> 8) & 0xff, cmd & 0xff);
294: if ((cmd & IOC_VOID) == 0)
295: printf(decimal ? ",%ld)" : ",%#lx)", (cmd >> 16) & 0xff);
296: else
297: printf(")");
298: }
1.1 deraadt 299:
300: ktrsyscall(ktr)
301: register struct ktr_syscall *ktr;
302: {
303: register argsize = ktr->ktr_argsize;
304: register register_t *ap;
305: char *ioctlname();
306:
307: if (ktr->ktr_code >= current->nsysnames || ktr->ktr_code < 0)
308: (void)printf("[%d]", ktr->ktr_code);
309: else
310: (void)printf("%s", current->sysnames[ktr->ktr_code]);
311: ap = (register_t *)((char *)ktr + sizeof(struct ktr_syscall));
312: if (argsize) {
313: char c = '(';
314: if (fancy) {
315: if (ktr->ktr_code == SYS_ioctl) {
316: char *cp;
317: if (decimal)
318: (void)printf("(%ld", (long)*ap);
319: else
320: (void)printf("(%#lx", (long)*ap);
321: ap++;
322: argsize -= sizeof(register_t);
323: if ((cp = ioctlname(*ap)) != NULL)
324: (void)printf(",%s", cp);
1.2 deraadt 325: else
326: ioctldecode(*ap);
1.1 deraadt 327: c = ',';
328: ap++;
329: argsize -= sizeof(register_t);
330: } else if (ktr->ktr_code == SYS_ptrace) {
331: if (*ap >= 0 && *ap <=
332: sizeof(ptrace_ops) / sizeof(ptrace_ops[0]))
333: (void)printf("(%s", ptrace_ops[*ap]);
334: else
335: (void)printf("(%ld", (long)*ap);
336: c = ',';
337: ap++;
338: argsize -= sizeof(register_t);
339: }
340: }
341: while (argsize) {
342: if (decimal)
343: (void)printf("%c%ld", c, (long)*ap);
344: else
345: (void)printf("%c%#lx", c, (long)*ap);
346: c = ',';
347: ap++;
348: argsize -= sizeof(register_t);
349: }
350: (void)putchar(')');
351: }
352: (void)putchar('\n');
353: }
354:
355: ktrsysret(ktr)
356: struct ktr_sysret *ktr;
357: {
358: register int ret = ktr->ktr_retval;
359: register int error = ktr->ktr_error;
360: register int code = ktr->ktr_code;
361:
362: if (code >= current->nsysnames || code < 0)
363: (void)printf("[%d] ", code);
364: else
365: (void)printf("%s ", current->sysnames[code]);
366:
367: if (error == 0) {
368: if (fancy) {
369: (void)printf("%d", ret);
370: if (ret < 0 || ret > 9)
371: (void)printf("/%#x", ret);
372: } else {
373: if (decimal)
374: (void)printf("%d", ret);
375: else
376: (void)printf("%#x", ret);
377: }
378: } else if (error == ERESTART)
379: (void)printf("RESTART");
380: else if (error == EJUSTRETURN)
381: (void)printf("JUSTRETURN");
382: else {
383: (void)printf("-1 errno %d", ktr->ktr_error);
384: if (fancy)
385: (void)printf(" %s", strerror(ktr->ktr_error));
386: }
387: (void)putchar('\n');
388: }
389:
390: ktrnamei(cp, len)
391: char *cp;
392: {
393: (void)printf("\"%.*s\"\n", len, cp);
394: }
395:
396: ktremul(cp, len)
397: char *cp;
398: {
399: char name[1024];
400:
401: if (len >= sizeof(name))
402: errx(1, "Emulation name too long");
403:
404: strncpy(name, cp, len);
405: name[len] = '\0';
406: (void)printf("\"%s\"\n", name);
407:
408: setemul(name);
409: }
410:
411: ktrgenio(ktr, len)
412: struct ktr_genio *ktr;
413: {
414: register int datalen = len - sizeof (struct ktr_genio);
415: register char *dp = (char *)ktr + sizeof (struct ktr_genio);
416: register char *cp;
417: register int col = 0;
418: register width;
419: char visbuf[5];
420: static screenwidth = 0;
421:
422: if (screenwidth == 0) {
423: struct winsize ws;
424:
425: if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 &&
426: ws.ws_col > 8)
427: screenwidth = ws.ws_col;
428: else
429: screenwidth = 80;
430: }
431: printf("fd %d %s %d bytes\n", ktr->ktr_fd,
432: ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen);
433: if (maxdata && datalen > maxdata)
434: datalen = maxdata;
435: (void)printf(" \"");
436: col = 8;
437: for (; datalen > 0; datalen--, dp++) {
438: (void) vis(visbuf, *dp, VIS_CSTYLE, *(dp+1));
439: cp = visbuf;
440: /*
441: * Keep track of printables and
442: * space chars (like fold(1)).
443: */
444: if (col == 0) {
445: (void)putchar('\t');
446: col = 8;
447: }
448: switch(*cp) {
449: case '\n':
450: col = 0;
451: (void)putchar('\n');
452: continue;
453: case '\t':
454: width = 8 - (col&07);
455: break;
456: default:
457: width = strlen(cp);
458: }
459: if (col + width > (screenwidth-2)) {
460: (void)printf("\\\n\t");
461: col = 8;
462: }
463: col += width;
464: do {
465: (void)putchar(*cp++);
466: } while (*cp);
467: }
468: if (col == 0)
469: (void)printf(" ");
470: (void)printf("\"\n");
471: }
472:
473: ktrpsig(psig)
474: struct ktr_psig *psig;
475: {
476: (void)printf("SIG%s ", sys_signame[psig->signo]);
477: if (psig->action == SIG_DFL)
478: (void)printf("SIG_DFL\n");
479: else
480: (void)printf("caught handler=0x%lx mask=0x%x code=0x%x\n",
481: (u_long)psig->action, psig->mask, psig->code);
482: }
483:
484: ktrcsw(cs)
485: struct ktr_csw *cs;
486: {
487: (void)printf("%s %s\n", cs->out ? "stop" : "resume",
488: cs->user ? "user" : "kernel");
489: }
490:
491: usage()
492: {
493:
494: (void)fprintf(stderr,
495: "usage: kdump [-dnlRT] [-e emulation] [-f trfile] [-m maxdata] [-t [cnis]]\n");
496: exit(1);
497: }
498:
499: setemul(name)
500: char *name;
501: {
502: int i;
503: for (i = 0; emulations[i].name != NULL; i++)
504: if (strcmp(emulations[i].name, name) == 0) {
505: current = &emulations[i];
506: return;
507: }
508: warnx("Emulation `%s' unknown", name);
509: }