Annotation of src/usr.bin/kdump/kdump.c, Revision 1.11
1.11 ! deraadt 1: /* $OpenBSD: kdump.c,v 1.10 1999/09/25 19:35:47 kstailey 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.11 ! deraadt 46: static char *rcsid = "$OpenBSD: kdump.c,v 1.10 1999/09/25 19:35:47 kstailey Exp $";
1.1 deraadt 47: #endif /* not lint */
48:
49: #include <sys/param.h>
50: #include <sys/time.h>
51: #include <sys/uio.h>
52: #include <sys/ktrace.h>
53: #include <sys/ioctl.h>
54: #include <sys/ptrace.h>
55: #define _KERNEL
56: #include <sys/errno.h>
57: #undef _KERNEL
58:
59: #include <err.h>
60: #include <signal.h>
61: #include <stdio.h>
62: #include <stdlib.h>
63: #include <string.h>
64: #include <unistd.h>
65: #include <vis.h>
66:
67: #include "ktrace.h"
68:
69: int timestamp, decimal, fancy = 1, tail, maxdata;
70: char *tracefile = DEF_TRACEFILE;
71: struct ktr_header ktr_header;
72:
73: #define eqs(s1, s2) (strcmp((s1), (s2)) == 0)
74:
75: #include <sys/syscall.h>
76:
1.9 deraadt 77: #include "../../sys/compat/bsdos/bsdos_syscall.h"
78: #include "../../sys/compat/freebsd/freebsd_syscall.h"
1.10 kstailey 79: #include "../../sys/compat/netbsd/netbsd_syscall.h"
1.1 deraadt 80: #include "../../sys/compat/hpux/hpux_syscall.h"
81: #include "../../sys/compat/ibcs2/ibcs2_syscall.h"
82: #include "../../sys/compat/linux/linux_syscall.h"
83: #include "../../sys/compat/osf1/osf1_syscall.h"
84: #include "../../sys/compat/sunos/sunos_syscall.h"
85: #include "../../sys/compat/svr4/svr4_syscall.h"
86: #include "../../sys/compat/ultrix/ultrix_syscall.h"
87:
88: #define KTRACE
1.7 deraadt 89: #define NFSCLIENT
90: #define NFSSERVER
91: #define SYSVSEM
92: #define SYSVMSG
93: #define SYSVSHM
94: #define LFS
95: #define NTP
1.1 deraadt 96: #include "../../sys/kern/syscalls.c"
97:
1.9 deraadt 98: #include "../../sys/compat/bsdos/bsdos_syscalls.c"
99: #include "../../sys/compat/freebsd/freebsd_syscalls.c"
1.10 kstailey 100: #include "../../sys/compat/netbsd/netbsd_syscalls.c"
1.1 deraadt 101: #include "../../sys/compat/hpux/hpux_syscalls.c"
102: #include "../../sys/compat/ibcs2/ibcs2_syscalls.c"
103: #include "../../sys/compat/linux/linux_syscalls.c"
104: #include "../../sys/compat/osf1/osf1_syscalls.c"
105: #include "../../sys/compat/sunos/sunos_syscalls.c"
106: #include "../../sys/compat/svr4/svr4_syscalls.c"
107: #include "../../sys/compat/ultrix/ultrix_syscalls.c"
108: #undef KTRACE
1.7 deraadt 109: #undef NFSCLIENT
110: #undef NFSSERVER
111: #undef SYSVSEM
112: #undef SYSVMSG
113: #undef SYSVSHM
114: #undef LFS
115: #undef NTP
1.1 deraadt 116:
117: struct emulation {
118: char *name; /* Emulation name */
119: char **sysnames; /* Array of system call names */
120: int nsysnames; /* Number of */
121: };
122:
123: static struct emulation emulations[] = {
1.9 deraadt 124: { "native", syscallnames, SYS_MAXSYSCALL },
125: { "hpux", hpux_syscallnames, HPUX_SYS_MAXSYSCALL },
126: { "ibcs2", ibcs2_syscallnames, IBCS2_SYS_MAXSYSCALL },
127: { "linux", linux_syscallnames, LINUX_SYS_MAXSYSCALL },
128: { "osf1", osf1_syscallnames, OSF1_SYS_MAXSYSCALL },
129: { "sunos", sunos_syscallnames, SUNOS_SYS_MAXSYSCALL },
130: { "svr4", svr4_syscallnames, SVR4_SYS_MAXSYSCALL },
131: { "ultrix", ultrix_syscallnames, ULTRIX_SYS_MAXSYSCALL },
132: { "bsdos", bsdos_syscallnames, BSDOS_SYS_MAXSYSCALL },
133: { "freebsd", freebsd_syscallnames, FREEBSD_SYS_MAXSYSCALL },
1.10 kstailey 134: { "netbsd", netbsd_syscallnames, NETBSD_SYS_MAXSYSCALL },
1.9 deraadt 135: { NULL, NULL, NULL }
1.1 deraadt 136: };
137:
138: struct emulation *current;
139:
140:
141: static char *ptrace_ops[] = {
142: "PT_TRACE_ME", "PT_READ_I", "PT_READ_D", "PT_READ_U",
143: "PT_WRITE_I", "PT_WRITE_D", "PT_WRITE_U", "PT_CONTINUE",
144: "PT_KILL", "PT_ATTACH", "PT_DETACH",
145: };
146:
147: int
148: main(argc, argv)
149: int argc;
150: char *argv[];
151: {
152: int ch, ktrlen, size;
153: register void *m;
154: int trpoints = ALL_POINTS;
155:
1.3 deraadt 156: current = &emulations[0]; /* native */
1.1 deraadt 157:
158: while ((ch = getopt(argc, argv, "e:f:dlm:nRTt:")) != -1)
159: switch (ch) {
160: case 'e':
161: setemul(optarg);
162: break;
163: case 'f':
164: tracefile = optarg;
165: break;
166: case 'd':
167: decimal = 1;
168: break;
169: case 'l':
170: tail = 1;
171: break;
172: case 'm':
173: maxdata = atoi(optarg);
174: break;
175: case 'n':
176: fancy = 0;
177: break;
178: case 'R':
179: timestamp = 2; /* relative timestamp */
180: break;
181: case 'T':
182: timestamp = 1;
183: break;
184: case 't':
185: trpoints = getpoints(optarg);
186: if (trpoints < 0)
187: errx(1, "unknown trace point in %s", optarg);
188: break;
189: default:
190: usage();
191: }
1.5 deraadt 192: if (argc > optind)
1.1 deraadt 193: usage();
194:
195: m = (void *)malloc(size = 1025);
196: if (m == NULL)
197: errx(1, "%s", strerror(ENOMEM));
198: if (!freopen(tracefile, "r", stdin))
199: err(1, "%s", tracefile);
200: while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) {
201: if (trpoints & (1<<ktr_header.ktr_type))
202: dumpheader(&ktr_header);
203: if ((ktrlen = ktr_header.ktr_len) < 0)
204: errx(1, "bogus length 0x%x", ktrlen);
205: if (ktrlen > size) {
206: m = (void *)realloc(m, ktrlen+1);
207: if (m == NULL)
208: errx(1, "%s", strerror(ENOMEM));
209: size = ktrlen;
210: }
211: if (ktrlen && fread_tail(m, ktrlen, 1) == 0)
212: errx(1, "data too short");
213: if ((trpoints & (1<<ktr_header.ktr_type)) == 0)
214: continue;
215: switch (ktr_header.ktr_type) {
216: case KTR_SYSCALL:
217: ktrsyscall((struct ktr_syscall *)m);
218: break;
219: case KTR_SYSRET:
220: ktrsysret((struct ktr_sysret *)m);
221: break;
222: case KTR_NAMEI:
223: ktrnamei(m, ktrlen);
224: break;
225: case KTR_GENIO:
226: ktrgenio((struct ktr_genio *)m, ktrlen);
227: break;
228: case KTR_PSIG:
229: ktrpsig((struct ktr_psig *)m);
230: break;
231: case KTR_CSW:
232: ktrcsw((struct ktr_csw *)m);
233: break;
234: case KTR_EMUL:
235: ktremul(m, ktrlen);
236: break;
237: }
238: if (tail)
239: (void)fflush(stdout);
240: }
241: }
242:
1.11 ! deraadt 243: int
1.1 deraadt 244: fread_tail(buf, size, num)
245: char *buf;
246: int num, size;
247: {
248: int i;
249:
250: while ((i = fread(buf, size, num, stdin)) == 0 && tail) {
251: (void)sleep(1);
252: clearerr(stdin);
253: }
254: return (i);
255: }
256:
1.11 ! deraadt 257: void
1.1 deraadt 258: dumpheader(kth)
259: struct ktr_header *kth;
260: {
261: char unknown[64], *type;
262: static struct timeval prevtime;
263: struct timeval temp;
264:
265: switch (kth->ktr_type) {
266: case KTR_SYSCALL:
267: type = "CALL";
268: break;
269: case KTR_SYSRET:
270: type = "RET ";
271: break;
272: case KTR_NAMEI:
273: type = "NAMI";
274: break;
275: case KTR_GENIO:
276: type = "GIO ";
277: break;
278: case KTR_PSIG:
279: type = "PSIG";
280: break;
281: case KTR_CSW:
282: type = "CSW";
283: break;
284: case KTR_EMUL:
285: type = "EMUL";
286: break;
287: default:
288: (void)sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type);
289: type = unknown;
290: }
291:
292: (void)printf("%6d %-8.*s ", kth->ktr_pid, MAXCOMLEN, kth->ktr_comm);
293: if (timestamp) {
294: if (timestamp == 2) {
295: timersub(&kth->ktr_time, &prevtime, &temp);
296: prevtime = kth->ktr_time;
297: } else
298: temp = kth->ktr_time;
299: (void)printf("%ld.%06ld ", temp.tv_sec, temp.tv_usec);
300: }
301: (void)printf("%s ", type);
302: }
303:
1.2 deraadt 304: void
305: ioctldecode(cmd)
306: u_long cmd;
307: {
308: char dirbuf[4], *dir = dirbuf;
309:
1.6 deraadt 310: if (cmd & IOC_IN)
311: *dir++ = 'W';
1.2 deraadt 312: if (cmd & IOC_OUT)
313: *dir++ = 'R';
314: *dir = '\0';
315:
316: printf(decimal ? ",_IO%s('%c',%ld" : ",_IO%s('%c',%#lx",
317: dirbuf, (cmd >> 8) & 0xff, cmd & 0xff);
318: if ((cmd & IOC_VOID) == 0)
319: printf(decimal ? ",%ld)" : ",%#lx)", (cmd >> 16) & 0xff);
320: else
321: printf(")");
322: }
1.1 deraadt 323:
1.11 ! deraadt 324: void
1.1 deraadt 325: ktrsyscall(ktr)
326: register struct ktr_syscall *ktr;
327: {
328: register argsize = ktr->ktr_argsize;
329: register register_t *ap;
330: char *ioctlname();
331:
332: if (ktr->ktr_code >= current->nsysnames || ktr->ktr_code < 0)
333: (void)printf("[%d]", ktr->ktr_code);
334: else
335: (void)printf("%s", current->sysnames[ktr->ktr_code]);
336: ap = (register_t *)((char *)ktr + sizeof(struct ktr_syscall));
337: if (argsize) {
338: char c = '(';
339: if (fancy) {
340: if (ktr->ktr_code == SYS_ioctl) {
341: char *cp;
342: if (decimal)
343: (void)printf("(%ld", (long)*ap);
344: else
345: (void)printf("(%#lx", (long)*ap);
346: ap++;
347: argsize -= sizeof(register_t);
348: if ((cp = ioctlname(*ap)) != NULL)
349: (void)printf(",%s", cp);
1.2 deraadt 350: else
351: ioctldecode(*ap);
1.1 deraadt 352: c = ',';
353: ap++;
354: argsize -= sizeof(register_t);
355: } else if (ktr->ktr_code == SYS_ptrace) {
356: if (*ap >= 0 && *ap <=
357: sizeof(ptrace_ops) / sizeof(ptrace_ops[0]))
358: (void)printf("(%s", ptrace_ops[*ap]);
359: else
360: (void)printf("(%ld", (long)*ap);
361: c = ',';
362: ap++;
363: argsize -= sizeof(register_t);
364: }
365: }
366: while (argsize) {
367: if (decimal)
368: (void)printf("%c%ld", c, (long)*ap);
369: else
370: (void)printf("%c%#lx", c, (long)*ap);
371: c = ',';
372: ap++;
373: argsize -= sizeof(register_t);
374: }
375: (void)putchar(')');
376: }
377: (void)putchar('\n');
378: }
379:
380: ktrsysret(ktr)
381: struct ktr_sysret *ktr;
382: {
383: register int ret = ktr->ktr_retval;
384: register int error = ktr->ktr_error;
385: register int code = ktr->ktr_code;
386:
387: if (code >= current->nsysnames || code < 0)
388: (void)printf("[%d] ", code);
389: else
390: (void)printf("%s ", current->sysnames[code]);
391:
392: if (error == 0) {
393: if (fancy) {
394: (void)printf("%d", ret);
395: if (ret < 0 || ret > 9)
396: (void)printf("/%#x", ret);
397: } else {
398: if (decimal)
399: (void)printf("%d", ret);
400: else
401: (void)printf("%#x", ret);
402: }
403: } else if (error == ERESTART)
404: (void)printf("RESTART");
405: else if (error == EJUSTRETURN)
406: (void)printf("JUSTRETURN");
407: else {
408: (void)printf("-1 errno %d", ktr->ktr_error);
409: if (fancy)
410: (void)printf(" %s", strerror(ktr->ktr_error));
411: }
412: (void)putchar('\n');
413: }
414:
415: ktrnamei(cp, len)
416: char *cp;
417: {
418: (void)printf("\"%.*s\"\n", len, cp);
419: }
420:
421: ktremul(cp, len)
422: char *cp;
423: {
424: char name[1024];
425:
426: if (len >= sizeof(name))
427: errx(1, "Emulation name too long");
428:
429: strncpy(name, cp, len);
430: name[len] = '\0';
431: (void)printf("\"%s\"\n", name);
432:
433: setemul(name);
434: }
435:
436: ktrgenio(ktr, len)
437: struct ktr_genio *ktr;
438: {
439: register int datalen = len - sizeof (struct ktr_genio);
440: register char *dp = (char *)ktr + sizeof (struct ktr_genio);
441: register char *cp;
442: register int col = 0;
443: register width;
444: char visbuf[5];
445: static screenwidth = 0;
446:
447: if (screenwidth == 0) {
448: struct winsize ws;
449:
450: if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 &&
451: ws.ws_col > 8)
452: screenwidth = ws.ws_col;
453: else
454: screenwidth = 80;
455: }
456: printf("fd %d %s %d bytes\n", ktr->ktr_fd,
457: ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen);
458: if (maxdata && datalen > maxdata)
459: datalen = maxdata;
460: (void)printf(" \"");
461: col = 8;
462: for (; datalen > 0; datalen--, dp++) {
463: (void) vis(visbuf, *dp, VIS_CSTYLE, *(dp+1));
464: cp = visbuf;
465: /*
466: * Keep track of printables and
467: * space chars (like fold(1)).
468: */
469: if (col == 0) {
470: (void)putchar('\t');
471: col = 8;
472: }
473: switch(*cp) {
474: case '\n':
475: col = 0;
476: (void)putchar('\n');
477: continue;
478: case '\t':
479: width = 8 - (col&07);
480: break;
481: default:
482: width = strlen(cp);
483: }
484: if (col + width > (screenwidth-2)) {
485: (void)printf("\\\n\t");
486: col = 8;
487: }
488: col += width;
489: do {
490: (void)putchar(*cp++);
491: } while (*cp);
492: }
493: if (col == 0)
494: (void)printf(" ");
495: (void)printf("\"\n");
496: }
497:
1.11 ! deraadt 498: void
1.1 deraadt 499: ktrpsig(psig)
500: struct ktr_psig *psig;
501: {
502: (void)printf("SIG%s ", sys_signame[psig->signo]);
503: if (psig->action == SIG_DFL)
504: (void)printf("SIG_DFL\n");
505: else
506: (void)printf("caught handler=0x%lx mask=0x%x code=0x%x\n",
507: (u_long)psig->action, psig->mask, psig->code);
508: }
509:
1.11 ! deraadt 510: void
1.1 deraadt 511: ktrcsw(cs)
512: struct ktr_csw *cs;
513: {
514: (void)printf("%s %s\n", cs->out ? "stop" : "resume",
515: cs->user ? "user" : "kernel");
516: }
517:
1.11 ! deraadt 518: void
1.1 deraadt 519: usage()
520: {
521:
522: (void)fprintf(stderr,
523: "usage: kdump [-dnlRT] [-e emulation] [-f trfile] [-m maxdata] [-t [cnis]]\n");
524: exit(1);
525: }
526:
1.11 ! deraadt 527: void
1.1 deraadt 528: setemul(name)
529: char *name;
530: {
531: int i;
532: for (i = 0; emulations[i].name != NULL; i++)
533: if (strcmp(emulations[i].name, name) == 0) {
534: current = &emulations[i];
535: return;
536: }
537: warnx("Emulation `%s' unknown", name);
538: }