Annotation of src/usr.bin/kdump/kdump.c, Revision 1.8
1.8 ! millert 1: /* $OpenBSD: kdump.c,v 1.7 1997/02/06 13:46:36 deraadt 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.8 ! millert 46: static char *rcsid = "$OpenBSD: kdump.c,v 1.7 1997/02/06 13:46:36 deraadt 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"
68:
69: int timestamp, decimal, fancy = 1, tail, maxdata;
70: char *tracefile = DEF_TRACEFILE;
71: struct ktr_header ktr_header;
72:
73: #define eqs(s1, s2) (strcmp((s1), (s2)) == 0)
74:
75: #include <sys/syscall.h>
76:
77: #include "../../sys/compat/hpux/hpux_syscall.h"
78: #include "../../sys/compat/ibcs2/ibcs2_syscall.h"
79: #include "../../sys/compat/linux/linux_syscall.h"
80: #include "../../sys/compat/osf1/osf1_syscall.h"
81: #include "../../sys/compat/sunos/sunos_syscall.h"
82: #include "../../sys/compat/svr4/svr4_syscall.h"
83: #include "../../sys/compat/ultrix/ultrix_syscall.h"
84:
85: #define KTRACE
1.7 deraadt 86: #define NFSCLIENT
87: #define NFSSERVER
88: #define SYSVSEM
89: #define SYSVMSG
90: #define SYSVSHM
91: #define LFS
92: #define NTP
1.1 deraadt 93: #include "../../sys/kern/syscalls.c"
94:
95: #include "../../sys/compat/hpux/hpux_syscalls.c"
96: #include "../../sys/compat/ibcs2/ibcs2_syscalls.c"
97: #include "../../sys/compat/linux/linux_syscalls.c"
98: #include "../../sys/compat/osf1/osf1_syscalls.c"
99: #include "../../sys/compat/sunos/sunos_syscalls.c"
100: #include "../../sys/compat/svr4/svr4_syscalls.c"
101: #include "../../sys/compat/ultrix/ultrix_syscalls.c"
102: #undef KTRACE
1.7 deraadt 103: #undef NFSCLIENT
104: #undef NFSSERVER
105: #undef SYSVSEM
106: #undef SYSVMSG
107: #undef SYSVSHM
108: #undef LFS
109: #undef NTP
1.1 deraadt 110:
111: struct emulation {
112: char *name; /* Emulation name */
113: char **sysnames; /* Array of system call names */
114: int nsysnames; /* Number of */
115: };
116:
117: static struct emulation emulations[] = {
1.3 deraadt 118: { "native", syscallnames, SYS_MAXSYSCALL },
1.1 deraadt 119: { "hpux", hpux_syscallnames, HPUX_SYS_MAXSYSCALL },
120: { "ibcs2", ibcs2_syscallnames, IBCS2_SYS_MAXSYSCALL },
121: { "linux", linux_syscallnames, LINUX_SYS_MAXSYSCALL },
122: { "osf1", osf1_syscallnames, OSF1_SYS_MAXSYSCALL },
123: { "sunos", sunos_syscallnames, SUNOS_SYS_MAXSYSCALL },
124: { "svr4", svr4_syscallnames, SVR4_SYS_MAXSYSCALL },
125: { "ultrix", ultrix_syscallnames, ULTRIX_SYS_MAXSYSCALL },
126: { NULL, NULL, NULL }
127: };
128:
129: struct emulation *current;
130:
131:
132: static char *ptrace_ops[] = {
133: "PT_TRACE_ME", "PT_READ_I", "PT_READ_D", "PT_READ_U",
134: "PT_WRITE_I", "PT_WRITE_D", "PT_WRITE_U", "PT_CONTINUE",
135: "PT_KILL", "PT_ATTACH", "PT_DETACH",
136: };
137:
138: int
139: main(argc, argv)
140: int argc;
141: char *argv[];
142: {
143: int ch, ktrlen, size;
144: register void *m;
145: int trpoints = ALL_POINTS;
146:
1.3 deraadt 147: current = &emulations[0]; /* native */
1.1 deraadt 148:
149: while ((ch = getopt(argc, argv, "e:f:dlm:nRTt:")) != -1)
150: switch (ch) {
151: case 'e':
152: setemul(optarg);
153: break;
154: case 'f':
155: tracefile = optarg;
156: break;
157: case 'd':
158: decimal = 1;
159: break;
160: case 'l':
161: tail = 1;
162: break;
163: case 'm':
164: maxdata = atoi(optarg);
165: break;
166: case 'n':
167: fancy = 0;
168: break;
169: case 'R':
170: timestamp = 2; /* relative timestamp */
171: break;
172: case 'T':
173: timestamp = 1;
174: break;
175: case 't':
176: trpoints = getpoints(optarg);
177: if (trpoints < 0)
178: errx(1, "unknown trace point in %s", optarg);
179: break;
180: default:
181: usage();
182: }
1.5 deraadt 183: if (argc > optind)
1.1 deraadt 184: usage();
185:
186: m = (void *)malloc(size = 1025);
187: if (m == NULL)
188: errx(1, "%s", strerror(ENOMEM));
189: if (!freopen(tracefile, "r", stdin))
190: err(1, "%s", tracefile);
191: while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) {
192: if (trpoints & (1<<ktr_header.ktr_type))
193: dumpheader(&ktr_header);
194: if ((ktrlen = ktr_header.ktr_len) < 0)
195: errx(1, "bogus length 0x%x", ktrlen);
196: if (ktrlen > size) {
197: m = (void *)realloc(m, ktrlen+1);
198: if (m == NULL)
199: errx(1, "%s", strerror(ENOMEM));
200: size = ktrlen;
201: }
202: if (ktrlen && fread_tail(m, ktrlen, 1) == 0)
203: errx(1, "data too short");
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: }
232: }
233:
234: fread_tail(buf, size, num)
235: char *buf;
236: int num, size;
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:
247: dumpheader(kth)
248: struct ktr_header *kth;
249: {
250: char unknown[64], *type;
251: static struct timeval prevtime;
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:
277: (void)sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type);
278: type = unknown;
279: }
280:
281: (void)printf("%6d %-8.*s ", kth->ktr_pid, MAXCOMLEN, kth->ktr_comm);
282: if (timestamp) {
283: if (timestamp == 2) {
284: timersub(&kth->ktr_time, &prevtime, &temp);
285: prevtime = kth->ktr_time;
286: } else
287: temp = kth->ktr_time;
288: (void)printf("%ld.%06ld ", temp.tv_sec, temp.tv_usec);
289: }
290: (void)printf("%s ", type);
291: }
292:
1.2 deraadt 293: void
294: ioctldecode(cmd)
295: u_long cmd;
296: {
297: char dirbuf[4], *dir = dirbuf;
298:
1.6 deraadt 299: if (cmd & IOC_IN)
300: *dir++ = 'W';
1.2 deraadt 301: if (cmd & IOC_OUT)
302: *dir++ = 'R';
303: *dir = '\0';
304:
305: printf(decimal ? ",_IO%s('%c',%ld" : ",_IO%s('%c',%#lx",
306: dirbuf, (cmd >> 8) & 0xff, cmd & 0xff);
307: if ((cmd & IOC_VOID) == 0)
308: printf(decimal ? ",%ld)" : ",%#lx)", (cmd >> 16) & 0xff);
309: else
310: printf(")");
311: }
1.1 deraadt 312:
313: ktrsyscall(ktr)
314: register struct ktr_syscall *ktr;
315: {
316: register argsize = ktr->ktr_argsize;
317: register register_t *ap;
318: char *ioctlname();
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));
325: if (argsize) {
326: char c = '(';
327: if (fancy) {
328: if (ktr->ktr_code == SYS_ioctl) {
329: char *cp;
330: if (decimal)
331: (void)printf("(%ld", (long)*ap);
332: else
333: (void)printf("(%#lx", (long)*ap);
334: ap++;
335: argsize -= sizeof(register_t);
336: if ((cp = ioctlname(*ap)) != NULL)
337: (void)printf(",%s", cp);
1.2 deraadt 338: else
339: ioctldecode(*ap);
1.1 deraadt 340: c = ',';
341: ap++;
342: argsize -= sizeof(register_t);
343: } else if (ktr->ktr_code == SYS_ptrace) {
344: if (*ap >= 0 && *ap <=
345: sizeof(ptrace_ops) / sizeof(ptrace_ops[0]))
346: (void)printf("(%s", ptrace_ops[*ap]);
347: else
348: (void)printf("(%ld", (long)*ap);
349: c = ',';
350: ap++;
351: argsize -= sizeof(register_t);
352: }
353: }
354: while (argsize) {
355: if (decimal)
356: (void)printf("%c%ld", c, (long)*ap);
357: else
358: (void)printf("%c%#lx", c, (long)*ap);
359: c = ',';
360: ap++;
361: argsize -= sizeof(register_t);
362: }
363: (void)putchar(')');
364: }
365: (void)putchar('\n');
366: }
367:
368: ktrsysret(ktr)
369: struct ktr_sysret *ktr;
370: {
371: register int ret = ktr->ktr_retval;
372: register int error = ktr->ktr_error;
373: register int code = ktr->ktr_code;
374:
375: if (code >= current->nsysnames || code < 0)
376: (void)printf("[%d] ", code);
377: else
378: (void)printf("%s ", current->sysnames[code]);
379:
380: if (error == 0) {
381: if (fancy) {
382: (void)printf("%d", ret);
383: if (ret < 0 || ret > 9)
384: (void)printf("/%#x", ret);
385: } else {
386: if (decimal)
387: (void)printf("%d", ret);
388: else
389: (void)printf("%#x", ret);
390: }
391: } else if (error == ERESTART)
392: (void)printf("RESTART");
393: else if (error == EJUSTRETURN)
394: (void)printf("JUSTRETURN");
395: else {
396: (void)printf("-1 errno %d", ktr->ktr_error);
397: if (fancy)
398: (void)printf(" %s", strerror(ktr->ktr_error));
399: }
400: (void)putchar('\n');
401: }
402:
403: ktrnamei(cp, len)
404: char *cp;
405: {
406: (void)printf("\"%.*s\"\n", len, cp);
407: }
408:
409: ktremul(cp, len)
410: char *cp;
411: {
412: char name[1024];
413:
414: if (len >= sizeof(name))
415: errx(1, "Emulation name too long");
416:
417: strncpy(name, cp, len);
418: name[len] = '\0';
419: (void)printf("\"%s\"\n", name);
420:
421: setemul(name);
422: }
423:
424: ktrgenio(ktr, len)
425: struct ktr_genio *ktr;
426: {
427: register int datalen = len - sizeof (struct ktr_genio);
428: register char *dp = (char *)ktr + sizeof (struct ktr_genio);
429: register char *cp;
430: register int col = 0;
431: register width;
432: char visbuf[5];
433: static screenwidth = 0;
434:
435: if (screenwidth == 0) {
436: struct winsize ws;
437:
438: if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 &&
439: ws.ws_col > 8)
440: screenwidth = ws.ws_col;
441: else
442: screenwidth = 80;
443: }
444: printf("fd %d %s %d bytes\n", ktr->ktr_fd,
445: ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen);
446: if (maxdata && datalen > maxdata)
447: datalen = maxdata;
448: (void)printf(" \"");
449: col = 8;
450: for (; datalen > 0; datalen--, dp++) {
451: (void) vis(visbuf, *dp, VIS_CSTYLE, *(dp+1));
452: cp = visbuf;
453: /*
454: * Keep track of printables and
455: * space chars (like fold(1)).
456: */
457: if (col == 0) {
458: (void)putchar('\t');
459: col = 8;
460: }
461: switch(*cp) {
462: case '\n':
463: col = 0;
464: (void)putchar('\n');
465: continue;
466: case '\t':
467: width = 8 - (col&07);
468: break;
469: default:
470: width = strlen(cp);
471: }
472: if (col + width > (screenwidth-2)) {
473: (void)printf("\\\n\t");
474: col = 8;
475: }
476: col += width;
477: do {
478: (void)putchar(*cp++);
479: } while (*cp);
480: }
481: if (col == 0)
482: (void)printf(" ");
483: (void)printf("\"\n");
484: }
485:
486: ktrpsig(psig)
487: struct ktr_psig *psig;
488: {
489: (void)printf("SIG%s ", sys_signame[psig->signo]);
490: if (psig->action == SIG_DFL)
491: (void)printf("SIG_DFL\n");
492: else
493: (void)printf("caught handler=0x%lx mask=0x%x code=0x%x\n",
494: (u_long)psig->action, psig->mask, psig->code);
495: }
496:
497: ktrcsw(cs)
498: struct ktr_csw *cs;
499: {
500: (void)printf("%s %s\n", cs->out ? "stop" : "resume",
501: cs->user ? "user" : "kernel");
502: }
503:
504: usage()
505: {
506:
507: (void)fprintf(stderr,
508: "usage: kdump [-dnlRT] [-e emulation] [-f trfile] [-m maxdata] [-t [cnis]]\n");
509: exit(1);
510: }
511:
512: setemul(name)
513: char *name;
514: {
515: int i;
516: for (i = 0; emulations[i].name != NULL; i++)
517: if (strcmp(emulations[i].name, name) == 0) {
518: current = &emulations[i];
519: return;
520: }
521: warnx("Emulation `%s' unknown", name);
522: }