Annotation of src/usr.bin/kdump/kdump.c, Revision 1.46
1.46 ! tedu 1: /* $OpenBSD: kdump.c,v 1.45 2010/07/01 17:26:52 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: #include <sys/param.h>
33: #include <sys/time.h>
34: #include <sys/uio.h>
35: #include <sys/ktrace.h>
36: #include <sys/ioctl.h>
37: #include <sys/ptrace.h>
1.28 deraadt 38: #include <sys/sysctl.h>
1.1 deraadt 39: #define _KERNEL
40: #include <sys/errno.h>
41: #undef _KERNEL
42:
1.33 tedu 43: #include <ctype.h>
1.1 deraadt 44: #include <err.h>
45: #include <signal.h>
46: #include <stdio.h>
47: #include <stdlib.h>
48: #include <string.h>
49: #include <unistd.h>
50: #include <vis.h>
51:
52: #include "ktrace.h"
1.22 deraadt 53: #include "kdump.h"
1.12 espie 54: #include "extern.h"
1.1 deraadt 55:
1.31 tedu 56: int timestamp, decimal, iohex, fancy = 1, tail, maxdata;
1.1 deraadt 57: char *tracefile = DEF_TRACEFILE;
58: struct ktr_header ktr_header;
1.17 deraadt 59: pid_t pid = -1;
1.1 deraadt 60:
61: #define eqs(s1, s2) (strcmp((s1), (s2)) == 0)
62:
63: #include <sys/syscall.h>
64:
1.25 mickey 65: #include <compat/bsdos/bsdos_syscall.h>
66: #include <compat/freebsd/freebsd_syscall.h>
67: #include <compat/linux/linux_syscall.h>
68: #include <compat/svr4/svr4_syscall.h>
1.1 deraadt 69:
70: #define KTRACE
1.19 mickey 71: #define PTRACE
1.7 deraadt 72: #define NFSCLIENT
73: #define NFSSERVER
74: #define SYSVSEM
75: #define SYSVMSG
76: #define SYSVSHM
77: #define LFS
1.30 miod 78: #define RTHREADS
1.25 mickey 79: #include <kern/syscalls.c>
1.1 deraadt 80:
1.25 mickey 81: #include <compat/bsdos/bsdos_syscalls.c>
82: #include <compat/freebsd/freebsd_syscalls.c>
83: #include <compat/linux/linux_syscalls.c>
84: #include <compat/svr4/svr4_syscalls.c>
1.1 deraadt 85: #undef KTRACE
1.19 mickey 86: #undef PTRACE
1.7 deraadt 87: #undef NFSCLIENT
88: #undef NFSSERVER
89: #undef SYSVSEM
90: #undef SYSVMSG
91: #undef SYSVSHM
92: #undef LFS
1.30 miod 93: #undef RTHREADS
1.1 deraadt 94:
95: struct emulation {
96: char *name; /* Emulation name */
97: char **sysnames; /* Array of system call names */
98: int nsysnames; /* Number of */
99: };
100:
101: static struct emulation emulations[] = {
1.9 deraadt 102: { "native", syscallnames, SYS_MAXSYSCALL },
103: { "linux", linux_syscallnames, LINUX_SYS_MAXSYSCALL },
104: { "svr4", svr4_syscallnames, SVR4_SYS_MAXSYSCALL },
105: { "bsdos", bsdos_syscallnames, BSDOS_SYS_MAXSYSCALL },
106: { "freebsd", freebsd_syscallnames, FREEBSD_SYS_MAXSYSCALL },
107: { NULL, NULL, NULL }
1.1 deraadt 108: };
109:
110: struct emulation *current;
111:
112:
113: static char *ptrace_ops[] = {
114: "PT_TRACE_ME", "PT_READ_I", "PT_READ_D", "PT_READ_U",
115: "PT_WRITE_I", "PT_WRITE_D", "PT_WRITE_U", "PT_CONTINUE",
1.15 art 116: "PT_KILL", "PT_ATTACH", "PT_DETACH", "PT_IO",
1.1 deraadt 117: };
118:
1.37 tedu 119: static int fread_tail(void *, size_t, size_t);
1.13 millert 120: static void dumpheader(struct ktr_header *);
121: static void ktrcsw(struct ktr_csw *);
1.37 tedu 122: static void ktremul(char *, size_t);
123: static void ktrgenio(struct ktr_genio *, size_t);
124: static void ktrnamei(const char *, size_t);
1.13 millert 125: static void ktrpsig(struct ktr_psig *);
126: static void ktrsyscall(struct ktr_syscall *);
127: static void ktrsysret(struct ktr_sysret *);
128: static void setemul(const char *);
129: static void usage(void);
1.12 espie 130:
1.1 deraadt 131: int
1.17 deraadt 132: main(int argc, char *argv[])
1.1 deraadt 133: {
1.37 tedu 134: int ch, silent;
135: size_t ktrlen, size;
1.17 deraadt 136: int trpoints = ALL_POINTS;
1.12 espie 137: void *m;
1.1 deraadt 138:
1.3 deraadt 139: current = &emulations[0]; /* native */
1.1 deraadt 140:
1.31 tedu 141: while ((ch = getopt(argc, argv, "e:f:dlm:nRp:Tt:xX")) != -1)
1.1 deraadt 142: switch (ch) {
143: case 'e':
144: setemul(optarg);
145: break;
146: case 'f':
147: tracefile = optarg;
148: break;
149: case 'd':
150: decimal = 1;
151: break;
152: case 'l':
153: tail = 1;
154: break;
155: case 'm':
156: maxdata = atoi(optarg);
157: break;
158: case 'n':
159: fancy = 0;
160: break;
1.17 deraadt 161: case 'p':
162: pid = atoi(optarg);
163: break;
1.1 deraadt 164: case 'R':
165: timestamp = 2; /* relative timestamp */
166: break;
167: case 'T':
168: timestamp = 1;
169: break;
170: case 't':
171: trpoints = getpoints(optarg);
172: if (trpoints < 0)
173: errx(1, "unknown trace point in %s", optarg);
174: break;
1.31 tedu 175: case 'x':
176: iohex = 1;
177: break;
178: case 'X':
179: iohex = 2;
180: break;
1.1 deraadt 181: default:
182: usage();
183: }
1.5 deraadt 184: if (argc > optind)
1.1 deraadt 185: usage();
186:
1.37 tedu 187: m = malloc(size = 1025);
1.1 deraadt 188: if (m == NULL)
1.37 tedu 189: err(1, NULL);
1.1 deraadt 190: if (!freopen(tracefile, "r", stdin))
191: err(1, "%s", tracefile);
192: while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) {
1.17 deraadt 193: silent = 0;
194: if (pid != -1 && pid != ktr_header.ktr_pid)
195: silent = 1;
196: if (silent == 0 && trpoints & (1<<ktr_header.ktr_type))
1.1 deraadt 197: dumpheader(&ktr_header);
1.37 tedu 198: ktrlen = ktr_header.ktr_len;
1.1 deraadt 199: if (ktrlen > size) {
1.23 tedu 200: void *newm;
201:
202: newm = realloc(m, ktrlen+1);
203: if (newm == NULL)
1.37 tedu 204: err(1, NULL);
1.23 tedu 205: m = newm;
1.1 deraadt 206: size = ktrlen;
207: }
208: if (ktrlen && fread_tail(m, ktrlen, 1) == 0)
209: errx(1, "data too short");
1.17 deraadt 210: if (silent)
211: continue;
1.1 deraadt 212: if ((trpoints & (1<<ktr_header.ktr_type)) == 0)
213: continue;
214: switch (ktr_header.ktr_type) {
215: case KTR_SYSCALL:
216: ktrsyscall((struct ktr_syscall *)m);
217: break;
218: case KTR_SYSRET:
219: ktrsysret((struct ktr_sysret *)m);
220: break;
221: case KTR_NAMEI:
222: ktrnamei(m, ktrlen);
223: break;
224: case KTR_GENIO:
225: ktrgenio((struct ktr_genio *)m, ktrlen);
226: break;
227: case KTR_PSIG:
228: ktrpsig((struct ktr_psig *)m);
229: break;
230: case KTR_CSW:
231: ktrcsw((struct ktr_csw *)m);
232: break;
233: case KTR_EMUL:
234: ktremul(m, ktrlen);
235: break;
236: }
237: if (tail)
238: (void)fflush(stdout);
239: }
1.12 espie 240: exit(0);
1.1 deraadt 241: }
242:
1.12 espie 243: static int
1.37 tedu 244: fread_tail(void *buf, size_t size, size_t num)
1.1 deraadt 245: {
246: int i;
247:
248: while ((i = fread(buf, size, num, stdin)) == 0 && tail) {
249: (void)sleep(1);
250: clearerr(stdin);
251: }
252: return (i);
253: }
254:
1.12 espie 255: static void
1.17 deraadt 256: dumpheader(struct ktr_header *kth)
1.1 deraadt 257: {
1.17 deraadt 258: static struct timeval prevtime;
1.1 deraadt 259: char unknown[64], *type;
260: struct timeval temp;
261:
262: switch (kth->ktr_type) {
263: case KTR_SYSCALL:
264: type = "CALL";
265: break;
266: case KTR_SYSRET:
267: type = "RET ";
268: break;
269: case KTR_NAMEI:
270: type = "NAMI";
271: break;
272: case KTR_GENIO:
273: type = "GIO ";
274: break;
275: case KTR_PSIG:
276: type = "PSIG";
277: break;
278: case KTR_CSW:
279: type = "CSW";
280: break;
281: case KTR_EMUL:
282: type = "EMUL";
283: break;
284: default:
1.17 deraadt 285: (void)snprintf(unknown, sizeof unknown, "UNKNOWN(%d)",
286: kth->ktr_type);
1.1 deraadt 287: type = unknown;
288: }
289:
1.16 mpech 290: (void)printf("%6ld %-8.*s ", (long)kth->ktr_pid, MAXCOMLEN,
291: kth->ktr_comm);
1.1 deraadt 292: if (timestamp) {
293: if (timestamp == 2) {
294: timersub(&kth->ktr_time, &prevtime, &temp);
295: prevtime = kth->ktr_time;
296: } else
297: temp = kth->ktr_time;
298: (void)printf("%ld.%06ld ", temp.tv_sec, temp.tv_usec);
299: }
300: (void)printf("%s ", type);
301: }
302:
1.12 espie 303: static void
1.17 deraadt 304: ioctldecode(u_long cmd)
1.2 deraadt 305: {
306: char dirbuf[4], *dir = dirbuf;
307:
1.6 deraadt 308: if (cmd & IOC_IN)
309: *dir++ = 'W';
1.2 deraadt 310: if (cmd & IOC_OUT)
311: *dir++ = 'R';
312: *dir = '\0';
313:
1.33 tedu 314: printf(decimal ? ",_IO%s('%c',%lu" : ",_IO%s('%c',%#lx",
315: dirbuf, (int)((cmd >> 8) & 0xff), cmd & 0xff);
1.2 deraadt 316: if ((cmd & IOC_VOID) == 0)
1.34 tedu 317: printf(decimal ? ",%lu)" : ",%#lx)", (cmd >> 16) & 0xff);
1.2 deraadt 318: else
319: printf(")");
320: }
1.1 deraadt 321:
1.12 espie 322: static void
1.17 deraadt 323: ktrsyscall(struct ktr_syscall *ktr)
1.1 deraadt 324: {
1.12 espie 325: int argsize = ktr->ktr_argsize;
326: register_t *ap;
1.1 deraadt 327:
328: if (ktr->ktr_code >= current->nsysnames || ktr->ktr_code < 0)
329: (void)printf("[%d]", ktr->ktr_code);
330: else
331: (void)printf("%s", current->sysnames[ktr->ktr_code]);
332: ap = (register_t *)((char *)ktr + sizeof(struct ktr_syscall));
1.27 mickey 333: (void)putchar('(');
1.1 deraadt 334: if (argsize) {
1.27 mickey 335: char c = '\0';
1.1 deraadt 336: if (fancy) {
337: if (ktr->ktr_code == SYS_ioctl) {
1.12 espie 338: const char *cp;
1.17 deraadt 339:
1.1 deraadt 340: if (decimal)
1.27 mickey 341: (void)printf("%ld", (long)*ap);
1.1 deraadt 342: else
1.27 mickey 343: (void)printf("%#lx", (long)*ap);
1.1 deraadt 344: ap++;
345: argsize -= sizeof(register_t);
346: if ((cp = ioctlname(*ap)) != NULL)
347: (void)printf(",%s", cp);
1.2 deraadt 348: else
349: ioctldecode(*ap);
1.1 deraadt 350: c = ',';
351: ap++;
352: argsize -= sizeof(register_t);
1.27 mickey 353: } else if (ktr->ktr_code == SYS___sysctl) {
354: int *np, n;
355:
356: n = ap[1];
1.28 deraadt 357: if (n > CTL_MAXNAME)
358: n = CTL_MAXNAME;
1.27 mickey 359: np = (int *)(ap + 6);
360: for (; n--; np++) {
361: if (c)
362: putchar(c);
363: printf("%d", *np);
364: c = '.';
365: }
366:
367: c = ',';
368: ap += 2;
369: argsize -= 2 * sizeof(register_t);
1.1 deraadt 370: } else if (ktr->ktr_code == SYS_ptrace) {
1.24 miod 371: if (*ap >= 0 && *ap <
1.1 deraadt 372: sizeof(ptrace_ops) / sizeof(ptrace_ops[0]))
1.27 mickey 373: (void)printf("%s", ptrace_ops[*ap]);
1.24 miod 374: else switch(*ap) {
375: #ifdef PT_GETFPREGS
376: case PT_GETFPREGS:
1.27 mickey 377: (void)printf("PT_GETFPREGS");
1.24 miod 378: break;
379: #endif
380: case PT_GETREGS:
1.27 mickey 381: (void)printf("PT_GETREGS");
1.24 miod 382: break;
383: #ifdef PT_SETFPREGS
384: case PT_SETFPREGS:
1.27 mickey 385: (void)printf("PT_SETFPREGS");
1.24 miod 386: break;
387: #endif
388: case PT_SETREGS:
1.27 mickey 389: (void)printf("PT_SETREGS");
1.24 miod 390: break;
391: #ifdef PT_STEP
392: case PT_STEP:
1.27 mickey 393: (void)printf("PT_STEP");
1.24 miod 394: break;
395: #endif
396: #ifdef PT_WCOOKIE
397: case PT_WCOOKIE:
1.27 mickey 398: (void)printf("PT_WCOOKIE");
1.24 miod 399: break;
400: #endif
401: default:
1.27 mickey 402: (void)printf("%ld", (long)*ap);
1.24 miod 403: break;
404: }
1.1 deraadt 405: c = ',';
406: ap++;
407: argsize -= sizeof(register_t);
408: }
409: }
410: while (argsize) {
1.27 mickey 411: if (c)
412: putchar(c);
1.1 deraadt 413: if (decimal)
1.27 mickey 414: (void)printf("%ld", (long)*ap);
1.1 deraadt 415: else
1.27 mickey 416: (void)printf("%#lx", (long)*ap);
1.1 deraadt 417: c = ',';
418: ap++;
419: argsize -= sizeof(register_t);
420: }
421: }
1.27 mickey 422: (void)printf(")\n");
1.1 deraadt 423: }
424:
1.12 espie 425: static void
1.17 deraadt 426: ktrsysret(struct ktr_sysret *ktr)
1.1 deraadt 427: {
1.12 espie 428: int ret = ktr->ktr_retval;
429: int error = ktr->ktr_error;
430: int code = ktr->ktr_code;
1.1 deraadt 431:
432: if (code >= current->nsysnames || code < 0)
433: (void)printf("[%d] ", code);
434: else
435: (void)printf("%s ", current->sysnames[code]);
436:
437: if (error == 0) {
438: if (fancy) {
439: (void)printf("%d", ret);
440: if (ret < 0 || ret > 9)
441: (void)printf("/%#x", ret);
442: } else {
443: if (decimal)
444: (void)printf("%d", ret);
445: else
446: (void)printf("%#x", ret);
447: }
448: } else if (error == ERESTART)
449: (void)printf("RESTART");
450: else if (error == EJUSTRETURN)
451: (void)printf("JUSTRETURN");
452: else {
453: (void)printf("-1 errno %d", ktr->ktr_error);
454: if (fancy)
455: (void)printf(" %s", strerror(ktr->ktr_error));
456: }
457: (void)putchar('\n');
458: }
459:
1.12 espie 460: static void
1.37 tedu 461: ktrnamei(const char *cp, size_t len)
1.1 deraadt 462: {
1.37 tedu 463: (void)printf("\"%.*s\"\n", (int)len, cp);
1.1 deraadt 464: }
465:
1.12 espie 466: static void
1.37 tedu 467: ktremul(char *cp, size_t len)
1.1 deraadt 468: {
469: char name[1024];
470:
471: if (len >= sizeof(name))
472: errx(1, "Emulation name too long");
473:
474: strncpy(name, cp, len);
475: name[len] = '\0';
476: (void)printf("\"%s\"\n", name);
477:
478: setemul(name);
479: }
480:
1.12 espie 481: static void
1.37 tedu 482: ktrgenio(struct ktr_genio *ktr, size_t len)
1.1 deraadt 483: {
1.37 tedu 484: unsigned char *dp = (unsigned char *)ktr + sizeof(struct ktr_genio);
485: int i, j;
486: size_t datalen = len - sizeof(struct ktr_genio);
1.12 espie 487: static int screenwidth = 0;
1.31 tedu 488: int col = 0, width, bpl;
1.32 tedu 489: unsigned char visbuf[5], *cp, c;
1.1 deraadt 490:
491: if (screenwidth == 0) {
492: struct winsize ws;
493:
494: if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 &&
495: ws.ws_col > 8)
496: screenwidth = ws.ws_col;
497: else
498: screenwidth = 80;
499: }
1.37 tedu 500: printf("fd %d %s %zu bytes\n", ktr->ktr_fd,
1.1 deraadt 501: ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen);
502: if (maxdata && datalen > maxdata)
503: datalen = maxdata;
1.31 tedu 504: if (iohex && !datalen)
505: return;
506: if (iohex == 1) {
507: putchar('\t');
508: col = 8;
509: for (i = 0; i < datalen; i++) {
1.35 tedu 510: printf("%02x", dp[i]);
1.31 tedu 511: col += 3;
512: if (i < datalen - 1) {
513: if (col + 3 > screenwidth) {
514: printf("\n\t");
515: col = 8;
516: } else
517: putchar(' ');
518: }
519: }
520: putchar('\n');
521: return;
522: }
523: if (iohex == 2) {
524: bpl = (screenwidth - 13)/4;
525: if (bpl <= 0)
526: bpl = 1;
527: for (i = 0; i < datalen; i += bpl) {
528: printf(" %04x: ", i);
529: for (j = 0; j < bpl; j++) {
530: if (i+j >= datalen)
531: printf(" ");
532: else
1.35 tedu 533: printf("%02x ", dp[i+j]);
1.31 tedu 534: }
535: putchar(' ');
536: for (j = 0; j < bpl; j++) {
537: if (i+j >= datalen)
538: break;
539: c = dp[i+j];
540: if (!isprint(c))
541: c = '.';
542: putchar(c);
543: }
544: putchar('\n');
545: }
546: return;
547: }
1.1 deraadt 548: (void)printf(" \"");
549: col = 8;
550: for (; datalen > 0; datalen--, dp++) {
1.31 tedu 551: (void)vis(visbuf, *dp, VIS_CSTYLE, *(dp+1));
1.1 deraadt 552: cp = visbuf;
1.17 deraadt 553:
1.1 deraadt 554: /*
555: * Keep track of printables and
556: * space chars (like fold(1)).
557: */
558: if (col == 0) {
559: (void)putchar('\t');
560: col = 8;
561: }
1.17 deraadt 562: switch (*cp) {
1.1 deraadt 563: case '\n':
564: col = 0;
565: (void)putchar('\n');
566: continue;
567: case '\t':
568: width = 8 - (col&07);
569: break;
570: default:
571: width = strlen(cp);
572: }
573: if (col + width > (screenwidth-2)) {
574: (void)printf("\\\n\t");
575: col = 8;
576: }
577: col += width;
578: do {
579: (void)putchar(*cp++);
580: } while (*cp);
581: }
582: if (col == 0)
583: (void)printf(" ");
584: (void)printf("\"\n");
585: }
586:
1.12 espie 587: static void
1.17 deraadt 588: ktrpsig(struct ktr_psig *psig)
1.1 deraadt 589: {
590: (void)printf("SIG%s ", sys_signame[psig->signo]);
591: if (psig->action == SIG_DFL)
1.14 deraadt 592: (void)printf("SIG_DFL code %d", psig->code);
1.1 deraadt 593: else
1.14 deraadt 594: (void)printf("caught handler=0x%lx mask=0x%x",
595: (u_long)psig->action, psig->mask);
596: switch (psig->signo) {
597: case SIGSEGV:
598: case SIGILL:
599: case SIGBUS:
600: case SIGFPE:
601: printf(" addr=%p trapno=%d", psig->si.si_addr,
602: psig->si.si_trapno);
603: break;
604: default:
605: break;
606: }
607: printf("\n");
1.1 deraadt 608: }
609:
1.12 espie 610: static void
1.17 deraadt 611: ktrcsw(struct ktr_csw *cs)
1.1 deraadt 612: {
613: (void)printf("%s %s\n", cs->out ? "stop" : "resume",
614: cs->user ? "user" : "kernel");
615: }
616:
1.12 espie 617: static void
1.17 deraadt 618: usage(void)
1.1 deraadt 619: {
620:
1.19 mickey 621: extern char *__progname;
622: fprintf(stderr, "usage: %s "
1.40 sobrado 623: "[-dlnRTXx] [-e emulation] [-f file] [-m maxdata] [-p pid]\n"
624: "%*s[-t [ceinsw]]\n",
625: __progname, sizeof("usage: ") + strlen(__progname), "");
1.1 deraadt 626: exit(1);
627: }
628:
1.12 espie 629: static void
1.17 deraadt 630: setemul(const char *name)
1.1 deraadt 631: {
632: int i;
1.17 deraadt 633:
1.1 deraadt 634: for (i = 0; emulations[i].name != NULL; i++)
635: if (strcmp(emulations[i].name, name) == 0) {
636: current = &emulations[i];
637: return;
638: }
639: warnx("Emulation `%s' unknown", name);
640: }