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