Annotation of src/usr.bin/kdump/kdump.c, Revision 1.24
1.24 ! miod 1: /* $OpenBSD: kdump.c,v 1.23 2003/10/13 00:44:25 tedu 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.
1.21 millert 15: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 16: * may be used to endorse or promote products derived from this software
17: * without specific prior written permission.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29: * SUCH DAMAGE.
30: */
31:
32: #ifndef lint
33: static char copyright[] =
34: "@(#) Copyright (c) 1988, 1993\n\
35: The Regents of the University of California. All rights reserved.\n";
36: #endif /* not lint */
37:
38: #ifndef lint
39: #if 0
40: static char sccsid[] = "@(#)kdump.c 8.4 (Berkeley) 4/28/95";
41: #endif
1.24 ! miod 42: static char *rcsid = "$OpenBSD: kdump.c,v 1.23 2003/10/13 00:44:25 tedu Exp $";
1.1 deraadt 43: #endif /* not lint */
44:
45: #include <sys/param.h>
46: #include <sys/time.h>
47: #include <sys/uio.h>
48: #include <sys/ktrace.h>
49: #include <sys/ioctl.h>
50: #include <sys/ptrace.h>
51: #define _KERNEL
52: #include <sys/errno.h>
53: #undef _KERNEL
54:
55: #include <err.h>
56: #include <signal.h>
57: #include <stdio.h>
58: #include <stdlib.h>
59: #include <string.h>
60: #include <unistd.h>
61: #include <vis.h>
62:
63: #include "ktrace.h"
1.22 deraadt 64: #include "kdump.h"
1.12 espie 65: #include "extern.h"
1.1 deraadt 66:
67: int timestamp, decimal, fancy = 1, tail, maxdata;
68: char *tracefile = DEF_TRACEFILE;
69: struct ktr_header ktr_header;
1.17 deraadt 70: pid_t pid = -1;
1.1 deraadt 71:
72: #define eqs(s1, s2) (strcmp((s1), (s2)) == 0)
73:
74: #include <sys/syscall.h>
75:
1.9 deraadt 76: #include "../../sys/compat/bsdos/bsdos_syscall.h"
77: #include "../../sys/compat/freebsd/freebsd_syscall.h"
1.10 kstailey 78: #include "../../sys/compat/netbsd/netbsd_syscall.h"
1.1 deraadt 79: #include "../../sys/compat/hpux/hpux_syscall.h"
80: #include "../../sys/compat/ibcs2/ibcs2_syscall.h"
81: #include "../../sys/compat/linux/linux_syscall.h"
82: #include "../../sys/compat/osf1/osf1_syscall.h"
83: #include "../../sys/compat/sunos/sunos_syscall.h"
84: #include "../../sys/compat/svr4/svr4_syscall.h"
85: #include "../../sys/compat/ultrix/ultrix_syscall.h"
86:
87: #define KTRACE
1.19 mickey 88: #define PTRACE
1.7 deraadt 89: #define NFSCLIENT
90: #define NFSSERVER
91: #define SYSVSEM
92: #define SYSVMSG
93: #define SYSVSHM
94: #define LFS
1.19 mickey 95: #define UFS_EXTATTR
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.19 mickey 109: #undef PTRACE
1.7 deraadt 110: #undef NFSCLIENT
111: #undef NFSSERVER
112: #undef SYSVSEM
113: #undef SYSVMSG
114: #undef SYSVSHM
115: #undef LFS
1.19 mickey 116: #undef UFS_EXTATTR
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",
1.15 art 145: "PT_KILL", "PT_ATTACH", "PT_DETACH", "PT_IO",
1.1 deraadt 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
1.17 deraadt 161: main(int argc, char *argv[])
1.1 deraadt 162: {
1.17 deraadt 163: int ch, ktrlen, size, silent;
164: int trpoints = ALL_POINTS;
1.12 espie 165: void *m;
1.1 deraadt 166:
1.3 deraadt 167: current = &emulations[0]; /* native */
1.1 deraadt 168:
1.17 deraadt 169: while ((ch = getopt(argc, argv, "e:f:dlm:nRp:Tt:")) != -1)
1.1 deraadt 170: switch (ch) {
171: case 'e':
172: setemul(optarg);
173: break;
174: case 'f':
175: tracefile = optarg;
176: break;
177: case 'd':
178: decimal = 1;
179: break;
180: case 'l':
181: tail = 1;
182: break;
183: case 'm':
184: maxdata = atoi(optarg);
185: break;
186: case 'n':
187: fancy = 0;
188: break;
1.17 deraadt 189: case 'p':
190: pid = atoi(optarg);
191: break;
1.1 deraadt 192: case 'R':
193: timestamp = 2; /* relative timestamp */
194: break;
195: case 'T':
196: timestamp = 1;
197: break;
198: case 't':
199: trpoints = getpoints(optarg);
200: if (trpoints < 0)
201: errx(1, "unknown trace point in %s", optarg);
202: break;
203: default:
204: usage();
205: }
1.5 deraadt 206: if (argc > optind)
1.1 deraadt 207: usage();
208:
209: m = (void *)malloc(size = 1025);
210: if (m == NULL)
211: errx(1, "%s", strerror(ENOMEM));
212: if (!freopen(tracefile, "r", stdin))
213: err(1, "%s", tracefile);
214: while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) {
1.17 deraadt 215: silent = 0;
216: if (pid != -1 && pid != ktr_header.ktr_pid)
217: silent = 1;
218: if (silent == 0 && trpoints & (1<<ktr_header.ktr_type))
1.1 deraadt 219: dumpheader(&ktr_header);
220: if ((ktrlen = ktr_header.ktr_len) < 0)
221: errx(1, "bogus length 0x%x", ktrlen);
222: if (ktrlen > size) {
1.23 tedu 223: void *newm;
224:
225: newm = realloc(m, ktrlen+1);
226: if (newm == NULL)
1.1 deraadt 227: errx(1, "%s", strerror(ENOMEM));
1.23 tedu 228: m = newm;
1.1 deraadt 229: size = ktrlen;
230: }
231: if (ktrlen && fread_tail(m, ktrlen, 1) == 0)
232: errx(1, "data too short");
1.17 deraadt 233: if (silent)
234: continue;
1.1 deraadt 235: if ((trpoints & (1<<ktr_header.ktr_type)) == 0)
236: continue;
237: switch (ktr_header.ktr_type) {
238: case KTR_SYSCALL:
239: ktrsyscall((struct ktr_syscall *)m);
240: break;
241: case KTR_SYSRET:
242: ktrsysret((struct ktr_sysret *)m);
243: break;
244: case KTR_NAMEI:
245: ktrnamei(m, ktrlen);
246: break;
247: case KTR_GENIO:
248: ktrgenio((struct ktr_genio *)m, ktrlen);
249: break;
250: case KTR_PSIG:
251: ktrpsig((struct ktr_psig *)m);
252: break;
253: case KTR_CSW:
254: ktrcsw((struct ktr_csw *)m);
255: break;
256: case KTR_EMUL:
257: ktremul(m, ktrlen);
258: break;
259: }
260: if (tail)
261: (void)fflush(stdout);
262: }
1.12 espie 263: exit(0);
1.1 deraadt 264: }
265:
1.12 espie 266: static int
1.17 deraadt 267: fread_tail(void *buf, int size, int num)
1.1 deraadt 268: {
269: int i;
270:
271: while ((i = fread(buf, size, num, stdin)) == 0 && tail) {
272: (void)sleep(1);
273: clearerr(stdin);
274: }
275: return (i);
276: }
277:
1.12 espie 278: static void
1.17 deraadt 279: dumpheader(struct ktr_header *kth)
1.1 deraadt 280: {
1.17 deraadt 281: static struct timeval prevtime;
1.1 deraadt 282: char unknown[64], *type;
283: struct timeval temp;
284:
285: switch (kth->ktr_type) {
286: case KTR_SYSCALL:
287: type = "CALL";
288: break;
289: case KTR_SYSRET:
290: type = "RET ";
291: break;
292: case KTR_NAMEI:
293: type = "NAMI";
294: break;
295: case KTR_GENIO:
296: type = "GIO ";
297: break;
298: case KTR_PSIG:
299: type = "PSIG";
300: break;
301: case KTR_CSW:
302: type = "CSW";
303: break;
304: case KTR_EMUL:
305: type = "EMUL";
306: break;
307: default:
1.17 deraadt 308: (void)snprintf(unknown, sizeof unknown, "UNKNOWN(%d)",
309: kth->ktr_type);
1.1 deraadt 310: type = unknown;
311: }
312:
1.16 mpech 313: (void)printf("%6ld %-8.*s ", (long)kth->ktr_pid, MAXCOMLEN,
314: kth->ktr_comm);
1.1 deraadt 315: if (timestamp) {
316: if (timestamp == 2) {
317: timersub(&kth->ktr_time, &prevtime, &temp);
318: prevtime = kth->ktr_time;
319: } else
320: temp = kth->ktr_time;
321: (void)printf("%ld.%06ld ", temp.tv_sec, temp.tv_usec);
322: }
323: (void)printf("%s ", type);
324: }
325:
1.12 espie 326: static void
1.17 deraadt 327: ioctldecode(u_long cmd)
1.2 deraadt 328: {
329: char dirbuf[4], *dir = dirbuf;
330:
1.6 deraadt 331: if (cmd & IOC_IN)
332: *dir++ = 'W';
1.2 deraadt 333: if (cmd & IOC_OUT)
334: *dir++ = 'R';
335: *dir = '\0';
336:
337: printf(decimal ? ",_IO%s('%c',%ld" : ",_IO%s('%c',%#lx",
338: dirbuf, (cmd >> 8) & 0xff, cmd & 0xff);
339: if ((cmd & IOC_VOID) == 0)
340: printf(decimal ? ",%ld)" : ",%#lx)", (cmd >> 16) & 0xff);
341: else
342: printf(")");
343: }
1.1 deraadt 344:
1.12 espie 345: static void
1.17 deraadt 346: ktrsyscall(struct ktr_syscall *ktr)
1.1 deraadt 347: {
1.12 espie 348: int argsize = ktr->ktr_argsize;
349: register_t *ap;
1.1 deraadt 350:
351: if (ktr->ktr_code >= current->nsysnames || ktr->ktr_code < 0)
352: (void)printf("[%d]", ktr->ktr_code);
353: else
354: (void)printf("%s", current->sysnames[ktr->ktr_code]);
355: ap = (register_t *)((char *)ktr + sizeof(struct ktr_syscall));
356: if (argsize) {
357: char c = '(';
358: if (fancy) {
359: if (ktr->ktr_code == SYS_ioctl) {
1.12 espie 360: const char *cp;
1.17 deraadt 361:
1.1 deraadt 362: if (decimal)
363: (void)printf("(%ld", (long)*ap);
364: else
365: (void)printf("(%#lx", (long)*ap);
366: ap++;
367: argsize -= sizeof(register_t);
368: if ((cp = ioctlname(*ap)) != NULL)
369: (void)printf(",%s", cp);
1.2 deraadt 370: else
371: ioctldecode(*ap);
1.1 deraadt 372: c = ',';
373: ap++;
374: argsize -= sizeof(register_t);
375: } else if (ktr->ktr_code == SYS_ptrace) {
1.24 ! miod 376: if (*ap >= 0 && *ap <
1.1 deraadt 377: sizeof(ptrace_ops) / sizeof(ptrace_ops[0]))
378: (void)printf("(%s", ptrace_ops[*ap]);
1.24 ! miod 379: else switch(*ap) {
! 380: #ifdef PT_GETFPREGS
! 381: case PT_GETFPREGS:
! 382: (void)printf("(PT_GETFPREGS");
! 383: break;
! 384: #endif
! 385: case PT_GETREGS:
! 386: (void)printf("(PT_GETREGS");
! 387: break;
! 388: #ifdef PT_SETFPREGS
! 389: case PT_SETFPREGS:
! 390: (void)printf("(PT_SETFPREGS");
! 391: break;
! 392: #endif
! 393: case PT_SETREGS:
! 394: (void)printf("(PT_SETREGS");
! 395: break;
! 396: #ifdef PT_STEP
! 397: case PT_STEP:
! 398: (void)printf("(PT_STEP");
! 399: break;
! 400: #endif
! 401: #ifdef PT_WCOOKIE
! 402: case PT_WCOOKIE:
! 403: (void)printf("(PT_WCOOKIE");
! 404: break;
! 405: #endif
! 406: default:
1.1 deraadt 407: (void)printf("(%ld", (long)*ap);
1.24 ! miod 408: break;
! 409: }
1.1 deraadt 410: c = ',';
411: ap++;
412: argsize -= sizeof(register_t);
413: }
414: }
415: while (argsize) {
416: if (decimal)
417: (void)printf("%c%ld", c, (long)*ap);
418: else
419: (void)printf("%c%#lx", c, (long)*ap);
420: c = ',';
421: ap++;
422: argsize -= sizeof(register_t);
423: }
424: (void)putchar(')');
425: }
426: (void)putchar('\n');
427: }
428:
1.12 espie 429: static void
1.17 deraadt 430: ktrsysret(struct ktr_sysret *ktr)
1.1 deraadt 431: {
1.12 espie 432: int ret = ktr->ktr_retval;
433: int error = ktr->ktr_error;
434: int code = ktr->ktr_code;
1.1 deraadt 435:
436: if (code >= current->nsysnames || code < 0)
437: (void)printf("[%d] ", code);
438: else
439: (void)printf("%s ", current->sysnames[code]);
440:
441: if (error == 0) {
442: if (fancy) {
443: (void)printf("%d", ret);
444: if (ret < 0 || ret > 9)
445: (void)printf("/%#x", ret);
446: } else {
447: if (decimal)
448: (void)printf("%d", ret);
449: else
450: (void)printf("%#x", ret);
451: }
452: } else if (error == ERESTART)
453: (void)printf("RESTART");
454: else if (error == EJUSTRETURN)
455: (void)printf("JUSTRETURN");
456: else {
457: (void)printf("-1 errno %d", ktr->ktr_error);
458: if (fancy)
459: (void)printf(" %s", strerror(ktr->ktr_error));
460: }
461: (void)putchar('\n');
462: }
463:
1.12 espie 464: static void
1.17 deraadt 465: ktrnamei(const char *cp, int len)
1.1 deraadt 466: {
467: (void)printf("\"%.*s\"\n", len, cp);
468: }
469:
1.12 espie 470: static void
1.17 deraadt 471: ktremul(char *cp, int len)
1.1 deraadt 472: {
473: char name[1024];
474:
475: if (len >= sizeof(name))
476: errx(1, "Emulation name too long");
477:
478: strncpy(name, cp, len);
479: name[len] = '\0';
480: (void)printf("\"%s\"\n", name);
481:
482: setemul(name);
483: }
484:
1.12 espie 485: static void
1.17 deraadt 486: ktrgenio(struct ktr_genio *ktr, int len)
1.1 deraadt 487: {
1.17 deraadt 488: char *dp = (char *)ktr + sizeof (struct ktr_genio);
1.12 espie 489: int datalen = len - sizeof (struct ktr_genio);
490: static int screenwidth = 0;
1.17 deraadt 491: int col = 0, width;
492: char visbuf[5], *cp;
1.1 deraadt 493:
494: if (screenwidth == 0) {
495: struct winsize ws;
496:
497: if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 &&
498: ws.ws_col > 8)
499: screenwidth = ws.ws_col;
500: else
501: screenwidth = 80;
502: }
503: printf("fd %d %s %d bytes\n", ktr->ktr_fd,
504: ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen);
505: if (maxdata && datalen > maxdata)
506: datalen = maxdata;
507: (void)printf(" \"");
508: col = 8;
509: for (; datalen > 0; datalen--, dp++) {
510: (void) vis(visbuf, *dp, VIS_CSTYLE, *(dp+1));
511: cp = visbuf;
1.17 deraadt 512:
1.1 deraadt 513: /*
514: * Keep track of printables and
515: * space chars (like fold(1)).
516: */
517: if (col == 0) {
518: (void)putchar('\t');
519: col = 8;
520: }
1.17 deraadt 521: switch (*cp) {
1.1 deraadt 522: case '\n':
523: col = 0;
524: (void)putchar('\n');
525: continue;
526: case '\t':
527: width = 8 - (col&07);
528: break;
529: default:
530: width = strlen(cp);
531: }
532: if (col + width > (screenwidth-2)) {
533: (void)printf("\\\n\t");
534: col = 8;
535: }
536: col += width;
537: do {
538: (void)putchar(*cp++);
539: } while (*cp);
540: }
541: if (col == 0)
542: (void)printf(" ");
543: (void)printf("\"\n");
544: }
545:
1.12 espie 546: static void
1.17 deraadt 547: ktrpsig(struct ktr_psig *psig)
1.1 deraadt 548: {
549: (void)printf("SIG%s ", sys_signame[psig->signo]);
550: if (psig->action == SIG_DFL)
1.14 deraadt 551: (void)printf("SIG_DFL code %d", psig->code);
1.1 deraadt 552: else
1.14 deraadt 553: (void)printf("caught handler=0x%lx mask=0x%x",
554: (u_long)psig->action, psig->mask);
555: switch (psig->signo) {
556: case SIGSEGV:
557: case SIGILL:
558: case SIGBUS:
559: case SIGFPE:
560: printf(" addr=%p trapno=%d", psig->si.si_addr,
561: psig->si.si_trapno);
562: break;
563: default:
564: break;
565: }
566: printf("\n");
1.1 deraadt 567: }
568:
1.12 espie 569: static void
1.17 deraadt 570: ktrcsw(struct ktr_csw *cs)
1.1 deraadt 571: {
572: (void)printf("%s %s\n", cs->out ? "stop" : "resume",
573: cs->user ? "user" : "kernel");
574: }
575:
1.12 espie 576: static void
1.17 deraadt 577: usage(void)
1.1 deraadt 578: {
579:
1.19 mickey 580: extern char *__progname;
581: fprintf(stderr, "usage: %s "
582: "[-dnlRT] [-e emulation] [-p pid] [-f trfile] [-m maxdata] "
1.20 deraadt 583: "[-t [ceinsw]]\n", __progname);
1.1 deraadt 584: exit(1);
585: }
586:
1.12 espie 587: static void
1.17 deraadt 588: setemul(const char *name)
1.1 deraadt 589: {
590: int i;
1.17 deraadt 591:
1.1 deraadt 592: for (i = 0; emulations[i].name != NULL; i++)
593: if (strcmp(emulations[i].name, name) == 0) {
594: current = &emulations[i];
595: return;
596: }
597: warnx("Emulation `%s' unknown", name);
598: }