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