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