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