Annotation of src/usr.bin/kdump/kdump.c, Revision 1.59
1.59 ! otto 1: /* $OpenBSD: kdump.c,v 1.58 2011/07/10 06:13:55 otto 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.51 otto 38: #include <sys/socket.h>
1.28 deraadt 39: #include <sys/sysctl.h>
1.55 otto 40: #include <sys/socket.h>
41: #include <sys/un.h>
42: #include <sys/stat.h>
43: #include <netinet/in.h>
44: #include <arpa/inet.h>
1.1 deraadt 45: #define _KERNEL
46: #include <sys/errno.h>
47: #undef _KERNEL
48:
1.33 tedu 49: #include <ctype.h>
1.1 deraadt 50: #include <err.h>
51: #include <signal.h>
52: #include <stdio.h>
53: #include <stdlib.h>
1.55 otto 54: #include <stdint.h>
1.1 deraadt 55: #include <string.h>
1.55 otto 56: #include <grp.h>
57: #include <pwd.h>
1.1 deraadt 58: #include <unistd.h>
59: #include <vis.h>
60:
61: #include "ktrace.h"
1.22 deraadt 62: #include "kdump.h"
1.51 otto 63: #include "kdump_subr.h"
1.12 espie 64: #include "extern.h"
1.1 deraadt 65:
1.58 otto 66: int timestamp, decimal, iohex, fancy = 1, tail, maxdata = INT_MAX, resolv;
1.1 deraadt 67: char *tracefile = DEF_TRACEFILE;
68: struct ktr_header ktr_header;
1.17 deraadt 69: pid_t pid = -1;
1.1 deraadt 70:
1.55 otto 71: #define TIME_FORMAT "%b %e %T %Y"
1.1 deraadt 72: #define eqs(s1, s2) (strcmp((s1), (s2)) == 0)
73:
74: #include <sys/syscall.h>
75:
1.25 mickey 76: #include <compat/linux/linux_syscall.h>
1.1 deraadt 77:
78: #define KTRACE
1.19 mickey 79: #define PTRACE
1.7 deraadt 80: #define NFSCLIENT
81: #define NFSSERVER
82: #define SYSVSEM
83: #define SYSVMSG
84: #define SYSVSHM
85: #define LFS
1.25 mickey 86: #include <kern/syscalls.c>
1.1 deraadt 87:
1.25 mickey 88: #include <compat/linux/linux_syscalls.c>
1.1 deraadt 89: #undef KTRACE
1.19 mickey 90: #undef PTRACE
1.7 deraadt 91: #undef NFSCLIENT
92: #undef NFSSERVER
93: #undef SYSVSEM
94: #undef SYSVMSG
95: #undef SYSVSHM
96: #undef LFS
1.1 deraadt 97:
98: struct emulation {
99: char *name; /* Emulation name */
100: char **sysnames; /* Array of system call names */
101: int nsysnames; /* Number of */
102: };
103:
104: static struct emulation emulations[] = {
1.9 deraadt 105: { "native", syscallnames, SYS_MAXSYSCALL },
106: { "linux", linux_syscallnames, LINUX_SYS_MAXSYSCALL },
1.49 miod 107: { NULL, NULL, 0 }
1.1 deraadt 108: };
109:
1.59 ! otto 110: static struct emulation *current;
! 111:
! 112: struct pid_emul {
! 113: struct emulation *e;
! 114: pid_t p;
! 115: };
! 116:
! 117: static struct pid_emul *pe_table;
! 118: static size_t pe_size;
1.1 deraadt 119:
120:
121: static char *ptrace_ops[] = {
122: "PT_TRACE_ME", "PT_READ_I", "PT_READ_D", "PT_READ_U",
123: "PT_WRITE_I", "PT_WRITE_D", "PT_WRITE_U", "PT_CONTINUE",
1.15 art 124: "PT_KILL", "PT_ATTACH", "PT_DETACH", "PT_IO",
1.1 deraadt 125: };
126:
1.52 otto 127: static int narg;
128: static register_t *ap;
129: static char sep;
130:
1.59 ! otto 131: static void mappidtoemul(pid_t, struct emulation *);
! 132: static struct emulation * findemul(pid_t);
1.37 tedu 133: static int fread_tail(void *, size_t, size_t);
1.13 millert 134: static void dumpheader(struct ktr_header *);
135: static void ktrcsw(struct ktr_csw *);
1.37 tedu 136: static void ktremul(char *, size_t);
137: static void ktrgenio(struct ktr_genio *, size_t);
138: static void ktrnamei(const char *, size_t);
1.13 millert 139: static void ktrpsig(struct ktr_psig *);
140: static void ktrsyscall(struct ktr_syscall *);
141: static void ktrsysret(struct ktr_sysret *);
1.55 otto 142: static void ktrstruct(char *, size_t);
1.13 millert 143: static void setemul(const char *);
144: static void usage(void);
1.12 espie 145:
1.1 deraadt 146: int
1.17 deraadt 147: main(int argc, char *argv[])
1.1 deraadt 148: {
1.37 tedu 149: int ch, silent;
150: size_t ktrlen, size;
1.17 deraadt 151: int trpoints = ALL_POINTS;
1.12 espie 152: void *m;
1.1 deraadt 153:
1.3 deraadt 154: current = &emulations[0]; /* native */
1.1 deraadt 155:
1.55 otto 156: while ((ch = getopt(argc, argv, "e:f:dlm:nrRp:Tt:xX")) != -1)
1.1 deraadt 157: switch (ch) {
158: case 'e':
159: setemul(optarg);
160: break;
161: case 'f':
162: tracefile = optarg;
163: break;
164: case 'd':
165: decimal = 1;
166: break;
167: case 'l':
168: tail = 1;
169: break;
170: case 'm':
171: maxdata = atoi(optarg);
172: break;
173: case 'n':
174: fancy = 0;
175: break;
1.17 deraadt 176: case 'p':
177: pid = atoi(optarg);
178: break;
1.55 otto 179: case 'r':
180: resolv = 1;
181: break;
1.1 deraadt 182: case 'R':
183: timestamp = 2; /* relative timestamp */
184: break;
185: case 'T':
186: timestamp = 1;
187: break;
188: case 't':
189: trpoints = getpoints(optarg);
190: if (trpoints < 0)
191: errx(1, "unknown trace point in %s", optarg);
192: break;
1.31 tedu 193: case 'x':
194: iohex = 1;
195: break;
196: case 'X':
197: iohex = 2;
198: break;
1.1 deraadt 199: default:
200: usage();
201: }
1.5 deraadt 202: if (argc > optind)
1.1 deraadt 203: usage();
204:
1.37 tedu 205: m = malloc(size = 1025);
1.1 deraadt 206: if (m == NULL)
1.37 tedu 207: err(1, NULL);
1.1 deraadt 208: if (!freopen(tracefile, "r", stdin))
209: err(1, "%s", tracefile);
210: while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) {
1.17 deraadt 211: silent = 0;
1.59 ! otto 212: if (pe_size == 0)
! 213: mappidtoemul(ktr_header.ktr_pid, current);
1.17 deraadt 214: if (pid != -1 && pid != ktr_header.ktr_pid)
215: silent = 1;
216: if (silent == 0 && trpoints & (1<<ktr_header.ktr_type))
1.1 deraadt 217: dumpheader(&ktr_header);
1.37 tedu 218: ktrlen = ktr_header.ktr_len;
1.1 deraadt 219: if (ktrlen > size) {
1.23 tedu 220: void *newm;
221:
222: newm = realloc(m, ktrlen+1);
223: if (newm == NULL)
1.37 tedu 224: err(1, NULL);
1.23 tedu 225: m = newm;
1.1 deraadt 226: size = ktrlen;
227: }
228: if (ktrlen && fread_tail(m, ktrlen, 1) == 0)
229: errx(1, "data too short");
1.17 deraadt 230: if (silent)
231: continue;
1.1 deraadt 232: if ((trpoints & (1<<ktr_header.ktr_type)) == 0)
233: continue;
1.59 ! otto 234: current = findemul(ktr_header.ktr_pid);
1.1 deraadt 235: switch (ktr_header.ktr_type) {
236: case KTR_SYSCALL:
237: ktrsyscall((struct ktr_syscall *)m);
238: break;
239: case KTR_SYSRET:
240: ktrsysret((struct ktr_sysret *)m);
241: break;
242: case KTR_NAMEI:
243: ktrnamei(m, ktrlen);
244: break;
245: case KTR_GENIO:
246: ktrgenio((struct ktr_genio *)m, ktrlen);
247: break;
248: case KTR_PSIG:
249: ktrpsig((struct ktr_psig *)m);
250: break;
251: case KTR_CSW:
252: ktrcsw((struct ktr_csw *)m);
253: break;
254: case KTR_EMUL:
255: ktremul(m, ktrlen);
1.59 ! otto 256: mappidtoemul(ktr_header.ktr_pid, current);
1.1 deraadt 257: break;
1.55 otto 258: case KTR_STRUCT:
259: ktrstruct(m, ktrlen);
260: break;
1.1 deraadt 261: }
262: if (tail)
263: (void)fflush(stdout);
264: }
1.12 espie 265: exit(0);
1.1 deraadt 266: }
267:
1.59 ! otto 268: static void
! 269: mappidtoemul(pid_t pid, struct emulation *emul)
! 270: {
! 271: size_t i;
! 272: struct pid_emul *tmp;
! 273:
! 274: for (i = 0; i < pe_size; i++) {
! 275: if (pe_table[i].p == pid) {
! 276: pe_table[i].e = emul;
! 277: return;
! 278: }
! 279: }
! 280: tmp = realloc(pe_table, (pe_size + 1) * sizeof(*pe_table));
! 281: if (tmp == NULL)
! 282: err(1, NULL);
! 283: pe_table = tmp;
! 284: pe_table[pe_size].p = pid;
! 285: pe_table[pe_size].e = emul;
! 286: pe_size++;
! 287: }
! 288:
! 289: static struct emulation*
! 290: findemul(pid_t pid)
! 291: {
! 292: size_t i;
! 293:
! 294: for (i = 0; i < pe_size; i++)
! 295: if (pe_table[i].p == pid)
! 296: return pe_table[i].e;
! 297: return current;
! 298: }
! 299:
1.12 espie 300: static int
1.37 tedu 301: fread_tail(void *buf, size_t size, size_t num)
1.1 deraadt 302: {
303: int i;
304:
305: while ((i = fread(buf, size, num, stdin)) == 0 && tail) {
306: (void)sleep(1);
307: clearerr(stdin);
308: }
309: return (i);
310: }
311:
1.12 espie 312: static void
1.17 deraadt 313: dumpheader(struct ktr_header *kth)
1.1 deraadt 314: {
1.17 deraadt 315: static struct timeval prevtime;
1.1 deraadt 316: char unknown[64], *type;
317: struct timeval temp;
318:
319: switch (kth->ktr_type) {
320: case KTR_SYSCALL:
321: type = "CALL";
322: break;
323: case KTR_SYSRET:
324: type = "RET ";
325: break;
326: case KTR_NAMEI:
327: type = "NAMI";
328: break;
329: case KTR_GENIO:
330: type = "GIO ";
331: break;
332: case KTR_PSIG:
333: type = "PSIG";
334: break;
335: case KTR_CSW:
336: type = "CSW";
337: break;
338: case KTR_EMUL:
339: type = "EMUL";
340: break;
1.55 otto 341: case KTR_STRUCT:
342: type = "STRU";
343: break;
1.1 deraadt 344: default:
1.17 deraadt 345: (void)snprintf(unknown, sizeof unknown, "UNKNOWN(%d)",
346: kth->ktr_type);
1.1 deraadt 347: type = unknown;
348: }
349:
1.16 mpech 350: (void)printf("%6ld %-8.*s ", (long)kth->ktr_pid, MAXCOMLEN,
351: kth->ktr_comm);
1.1 deraadt 352: if (timestamp) {
353: if (timestamp == 2) {
354: timersub(&kth->ktr_time, &prevtime, &temp);
355: prevtime = kth->ktr_time;
356: } else
357: temp = kth->ktr_time;
358: (void)printf("%ld.%06ld ", temp.tv_sec, temp.tv_usec);
359: }
360: (void)printf("%s ", type);
361: }
362:
1.12 espie 363: static void
1.17 deraadt 364: ioctldecode(u_long cmd)
1.2 deraadt 365: {
366: char dirbuf[4], *dir = dirbuf;
367:
1.6 deraadt 368: if (cmd & IOC_IN)
369: *dir++ = 'W';
1.2 deraadt 370: if (cmd & IOC_OUT)
371: *dir++ = 'R';
372: *dir = '\0';
373:
1.33 tedu 374: printf(decimal ? ",_IO%s('%c',%lu" : ",_IO%s('%c',%#lx",
375: dirbuf, (int)((cmd >> 8) & 0xff), cmd & 0xff);
1.2 deraadt 376: if ((cmd & IOC_VOID) == 0)
1.34 tedu 377: printf(decimal ? ",%lu)" : ",%#lx)", (cmd >> 16) & 0xff);
1.2 deraadt 378: else
379: printf(")");
380: }
1.1 deraadt 381:
1.52 otto 382: static void
383: ptracedecode(void)
384: {
385: if (*ap >= 0 && *ap <
386: sizeof(ptrace_ops) / sizeof(ptrace_ops[0]))
387: (void)printf("%s", ptrace_ops[*ap]);
388: else switch(*ap) {
389: #ifdef PT_GETFPREGS
390: case PT_GETFPREGS:
391: (void)printf("PT_GETFPREGS");
392: break;
393: #endif
394: case PT_GETREGS:
395: (void)printf("PT_GETREGS");
396: break;
397: #ifdef PT_SETFPREGS
398: case PT_SETFPREGS:
399: (void)printf("PT_SETFPREGS");
400: break;
401: #endif
402: case PT_SETREGS:
403: (void)printf("PT_SETREGS");
404: break;
405: #ifdef PT_STEP
406: case PT_STEP:
407: (void)printf("PT_STEP");
408: break;
409: #endif
410: #ifdef PT_WCOOKIE
411: case PT_WCOOKIE:
412: (void)printf("PT_WCOOKIE");
413: break;
414: #endif
415: default:
416: (void)printf("%ld", (long)*ap);
417: break;
418: }
419: sep = ',';
420: ap++;
421: narg--;
422: }
423:
424: static void
425: pn(void (*f)(int))
426: {
427: if (sep)
428: (void)putchar(sep);
429: if (fancy && f != NULL)
430: f((int)*ap);
431: else if (decimal)
432: (void)printf("%ld", (long)*ap);
433: else
434: (void)printf("%#lx", (long)*ap);
435: ap++;
436: narg--;
437: sep = ',';
438: }
439:
440: #ifdef __LP64__
441: #define plln() pn(NULL)
442: #elif _BYTE_ORDER == _LITTLE_ENDIAN
443: static void
444: plln(void)
445: {
446: long long val = ((long long)*ap) & 0xffffffff;
447: ap++;
448: val |= ((long long)*ap) << 32;
449: ap++;
450: narg -= 2;
451: if (sep)
452: (void)putchar(sep);
453: if (decimal)
454: (void)printf("%lld", val);
455: else
456: (void)printf("%#llx", val);
457: sep = ',';
458: }
459: #else
460: static void
461: plln(void)
462: {
463: long long val = ((long long)*ap) << 32;
464: ap++;
465: val |= ((long long)*ap) & 0xffffffff;
466: ap++;
467: narg -= 2;
468: if (sep)
469: (void)putchar(sep);
470: if (decimal)
471: (void)printf("%lld", val);
472: else
473: (void)printf("%#llx", val);
474: sep = ',';
475: }
476: #endif
1.51 otto 477:
1.12 espie 478: static void
1.17 deraadt 479: ktrsyscall(struct ktr_syscall *ktr)
1.1 deraadt 480: {
1.52 otto 481: narg = ktr->ktr_argsize / sizeof(register_t);
482: sep = '\0';
1.1 deraadt 483:
484: if (ktr->ktr_code >= current->nsysnames || ktr->ktr_code < 0)
485: (void)printf("[%d]", ktr->ktr_code);
486: else
487: (void)printf("%s", current->sysnames[ktr->ktr_code]);
488: ap = (register_t *)((char *)ktr + sizeof(struct ktr_syscall));
1.27 mickey 489: (void)putchar('(');
1.52 otto 490:
1.54 otto 491: if (current != &emulations[0])
492: goto nonnative;
493:
1.52 otto 494: switch (ktr->ktr_code) {
495: case SYS_ioctl: {
496: const char *cp;
497:
498: pn(NULL);
499: if (!fancy)
500: break;
501: if ((cp = ioctlname(*ap)) != NULL)
502: (void)printf(",%s", cp);
503: else
504: ioctldecode(*ap);
505: ap++;
506: narg--;
507: break;
508: }
509: case SYS___sysctl: {
510: int *np, n;
511:
512: if (!fancy)
513: break;
514: n = ap[1];
515: if (n > CTL_MAXNAME)
516: n = CTL_MAXNAME;
517: np = (int *)(ap + 6);
518: for (; n--; np++) {
519: if (sep)
520: putchar(sep);
521: printf("%d", *np);
522: sep = '.';
1.1 deraadt 523: }
1.52 otto 524:
525: sep = ',';
526: ap += 2;
527: narg -= 2;
528: break;
529: }
530: case SYS_ptrace:
531: if (!fancy)
532: break;
533: ptracedecode();
534: break;
535: case SYS_access:
536: pn(NULL);
537: pn(accessmodename);
538: break;
539: case SYS_chmod:
540: case SYS_fchmod:
541: pn( NULL);
542: pn(modename);
543: break;
544: case SYS_fcntl: {
545: int cmd;
546: int arg;
547: pn(NULL);
548: if (!fancy)
549: break;
550: cmd = ap[0];
551: arg = ap[1];
552: (void)putchar(',');
553: fcntlcmdname(cmd, arg);
554: ap += 2;
555: narg -= 2;
556: break;
557: }
558: case SYS_flock:
559: pn(NULL);
560: pn(flockname);
561: break;
562: case SYS_getrlimit:
563: case SYS_setrlimit:
564: pn(rlimitname);
565: break;
566: case SYS_getsockopt:
567: case SYS_setsockopt: {
568: int level;
569:
570: pn(NULL);
571: level = *ap;
572: pn(sockoptlevelname);
573: if (level == SOL_SOCKET)
574: pn(sockoptname);
575: break;
576: }
577: case SYS_kill:
578: pn(NULL);
579: pn(signame);
580: break;
581: case SYS_lseek:
582: pn(NULL);
583: /* skip padding */
584: ap++;
585: narg--;
586: plln();
587: pn(whencename);
588: break;
589: case SYS_madvise:
590: pn(NULL);
591: pn(NULL);
592: pn(madvisebehavname);
593: break;
594: case SYS_minherit:
595: pn(NULL);
596: pn(NULL);
597: pn(minheritname);
598: break;
599: case SYS_mlockall:
600: pn(mlockallname);
601: break;
602: case SYS_mmap:
603: pn(NULL);
604: pn(NULL);
605: pn(mmapprotname);
606: pn(mmapflagsname);
607: pn(NULL);
608: /* skip padding */
609: ap++;
610: narg--;
611: plln();
612: break;
613: case SYS_mprotect:
614: pn(NULL);
615: pn(NULL);
616: pn(mmapprotname);
617: break;
618: case SYS_mquery:
619: pn(NULL);
620: pn(NULL);
621: pn(mmapprotname);
622: pn(mmapflagsname);
623: pn(NULL);
624: /* skip padding */
625: ap++;
626: narg--;
627: plln();
628: break;
629: case SYS_msync:
630: pn(NULL);
631: pn(NULL);
632: pn(msyncflagsname);
633: break;
634: case SYS_msgctl:
635: pn(NULL);
636: pn(shmctlname);
637: break;
638: case SYS_open: {
639: int flags;
640: int mode;
641:
642: pn(NULL);
643: if (!fancy)
644: break;
645: flags = ap[0];
646: mode = ap[1];
647: (void)putchar(',');
648: flagsandmodename(flags, mode);
649: ap += 2;
650: narg -= 2;
651: break;
652: }
653: case SYS_pread:
654: case SYS_preadv:
655: case SYS_pwrite:
656: case SYS_pwritev:
657: pn(NULL);
658: pn(NULL);
659: pn(NULL);
660: /* skip padding */
661: ap++;
662: narg--;
663: plln();
664: break;
665: case SYS_recvmsg:
666: case SYS_sendmsg:
667: pn(NULL);
668: pn(NULL);
669: pn(sendrecvflagsname);
670: break;
671: case SYS_recvfrom:
672: case SYS_sendto:
673: pn(NULL);
674: pn(NULL);
675: pn(NULL);
676: pn(sendrecvflagsname);
677: break;
678: case SYS___semctl:
679: pn(NULL);
680: pn(NULL);
681: pn(semctlname);
682: break;
683: case SYS_semget:
684: pn(NULL);
685: pn(NULL);
686: pn(semgetname);
687: break;
688: case SYS_shmat:
689: pn(NULL);
690: pn(NULL);
691: pn(shmatname);
692: break;
693: case SYS_shmctl:
694: pn(NULL);
695: pn(shmctlname);
696: break;
697: case SYS_sigaction:
698: pn(signame);
699: break;
700: case SYS_sigprocmask:
701: pn(sigprocmaskhowname);
702: break;
703: case SYS_socket: {
704: int sockdomain = *ap;
705:
706: pn(sockdomainname);
707: pn(socktypename);
708: if (sockdomain == PF_INET || sockdomain == PF_INET6)
709: pn(sockipprotoname);
710: break;
711: }
712: case SYS_socketpair:
713: pn(sockdomainname);
714: pn(socktypename);
715: break;
716: case SYS_truncate:
717: case SYS_ftruncate:
718: pn(NULL);
719: /* skip padding */
720: ap++;
721: narg--;
722: plln();
723: break;
724: case SYS_wait4:
725: pn(NULL);
726: pn(NULL);
727: pn(wait4optname);
728: break;
729: }
730:
1.54 otto 731: nonnative:
1.52 otto 732: while (narg) {
733: if (sep)
734: putchar(sep);
735: if (decimal)
736: (void)printf("%ld", (long)*ap);
737: else
738: (void)printf("%#lx", (long)*ap);
739: sep = ',';
740: ap++;
741: narg--;
1.1 deraadt 742: }
1.27 mickey 743: (void)printf(")\n");
1.1 deraadt 744: }
745:
1.12 espie 746: static void
1.17 deraadt 747: ktrsysret(struct ktr_sysret *ktr)
1.1 deraadt 748: {
1.50 deraadt 749: register_t ret = ktr->ktr_retval;
1.12 espie 750: int error = ktr->ktr_error;
751: int code = ktr->ktr_code;
1.1 deraadt 752:
753: if (code >= current->nsysnames || code < 0)
754: (void)printf("[%d] ", code);
1.59 ! otto 755: else {
1.1 deraadt 756: (void)printf("%s ", current->sysnames[code]);
1.59 ! otto 757: if (ret > 0 && (strcmp(current->sysnames[code], "fork") == 0 ||
! 758: strcmp(current->sysnames[code], "vfork") == 0 ||
! 759: strcmp(current->sysnames[code], "rfork") == 0 ||
! 760: strcmp(current->sysnames[code], "clone") == 0))
! 761: mappidtoemul(ret, current);
! 762: }
1.1 deraadt 763:
764: if (error == 0) {
765: if (fancy) {
1.50 deraadt 766: (void)printf("%ld", (long)ret);
1.1 deraadt 767: if (ret < 0 || ret > 9)
1.50 deraadt 768: (void)printf("/%#lx", (long)ret);
1.1 deraadt 769: } else {
770: if (decimal)
1.50 deraadt 771: (void)printf("%ld", (long)ret);
1.1 deraadt 772: else
1.50 deraadt 773: (void)printf("%#lx", (long)ret);
1.1 deraadt 774: }
775: } else if (error == ERESTART)
776: (void)printf("RESTART");
777: else if (error == EJUSTRETURN)
778: (void)printf("JUSTRETURN");
779: else {
780: (void)printf("-1 errno %d", ktr->ktr_error);
781: if (fancy)
782: (void)printf(" %s", strerror(ktr->ktr_error));
783: }
784: (void)putchar('\n');
785: }
786:
1.12 espie 787: static void
1.37 tedu 788: ktrnamei(const char *cp, size_t len)
1.1 deraadt 789: {
1.37 tedu 790: (void)printf("\"%.*s\"\n", (int)len, cp);
1.1 deraadt 791: }
792:
1.12 espie 793: static void
1.37 tedu 794: ktremul(char *cp, size_t len)
1.1 deraadt 795: {
796: char name[1024];
797:
798: if (len >= sizeof(name))
799: errx(1, "Emulation name too long");
800:
801: strncpy(name, cp, len);
802: name[len] = '\0';
803: (void)printf("\"%s\"\n", name);
804:
805: setemul(name);
806: }
807:
1.12 espie 808: static void
1.37 tedu 809: ktrgenio(struct ktr_genio *ktr, size_t len)
1.1 deraadt 810: {
1.37 tedu 811: unsigned char *dp = (unsigned char *)ktr + sizeof(struct ktr_genio);
812: int i, j;
813: size_t datalen = len - sizeof(struct ktr_genio);
1.12 espie 814: static int screenwidth = 0;
1.31 tedu 815: int col = 0, width, bpl;
1.32 tedu 816: unsigned char visbuf[5], *cp, c;
1.1 deraadt 817:
818: if (screenwidth == 0) {
819: struct winsize ws;
820:
821: if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 &&
822: ws.ws_col > 8)
823: screenwidth = ws.ws_col;
824: else
825: screenwidth = 80;
826: }
1.37 tedu 827: printf("fd %d %s %zu bytes\n", ktr->ktr_fd,
1.1 deraadt 828: ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen);
1.58 otto 829: if (maxdata == 0)
830: return;
831: if (datalen > maxdata)
1.1 deraadt 832: datalen = maxdata;
1.31 tedu 833: if (iohex && !datalen)
834: return;
835: if (iohex == 1) {
836: putchar('\t');
837: col = 8;
838: for (i = 0; i < datalen; i++) {
1.35 tedu 839: printf("%02x", dp[i]);
1.31 tedu 840: col += 3;
841: if (i < datalen - 1) {
842: if (col + 3 > screenwidth) {
843: printf("\n\t");
844: col = 8;
845: } else
846: putchar(' ');
847: }
848: }
849: putchar('\n');
850: return;
851: }
852: if (iohex == 2) {
853: bpl = (screenwidth - 13)/4;
854: if (bpl <= 0)
855: bpl = 1;
856: for (i = 0; i < datalen; i += bpl) {
857: printf(" %04x: ", i);
858: for (j = 0; j < bpl; j++) {
859: if (i+j >= datalen)
860: printf(" ");
861: else
1.35 tedu 862: printf("%02x ", dp[i+j]);
1.31 tedu 863: }
864: putchar(' ');
865: for (j = 0; j < bpl; j++) {
866: if (i+j >= datalen)
867: break;
868: c = dp[i+j];
869: if (!isprint(c))
870: c = '.';
871: putchar(c);
872: }
873: putchar('\n');
874: }
875: return;
876: }
1.1 deraadt 877: (void)printf(" \"");
878: col = 8;
879: for (; datalen > 0; datalen--, dp++) {
1.31 tedu 880: (void)vis(visbuf, *dp, VIS_CSTYLE, *(dp+1));
1.1 deraadt 881: cp = visbuf;
1.17 deraadt 882:
1.1 deraadt 883: /*
884: * Keep track of printables and
885: * space chars (like fold(1)).
886: */
887: if (col == 0) {
888: (void)putchar('\t');
889: col = 8;
890: }
1.17 deraadt 891: switch (*cp) {
1.1 deraadt 892: case '\n':
893: col = 0;
894: (void)putchar('\n');
895: continue;
896: case '\t':
897: width = 8 - (col&07);
898: break;
899: default:
900: width = strlen(cp);
901: }
902: if (col + width > (screenwidth-2)) {
903: (void)printf("\\\n\t");
904: col = 8;
905: }
906: col += width;
907: do {
908: (void)putchar(*cp++);
909: } while (*cp);
910: }
911: if (col == 0)
912: (void)printf(" ");
913: (void)printf("\"\n");
914: }
915:
1.12 espie 916: static void
1.17 deraadt 917: ktrpsig(struct ktr_psig *psig)
1.1 deraadt 918: {
919: (void)printf("SIG%s ", sys_signame[psig->signo]);
920: if (psig->action == SIG_DFL)
1.14 deraadt 921: (void)printf("SIG_DFL code %d", psig->code);
1.1 deraadt 922: else
1.14 deraadt 923: (void)printf("caught handler=0x%lx mask=0x%x",
924: (u_long)psig->action, psig->mask);
925: switch (psig->signo) {
926: case SIGSEGV:
927: case SIGILL:
928: case SIGBUS:
929: case SIGFPE:
930: printf(" addr=%p trapno=%d", psig->si.si_addr,
931: psig->si.si_trapno);
932: break;
933: default:
934: break;
935: }
936: printf("\n");
1.1 deraadt 937: }
938:
1.12 espie 939: static void
1.17 deraadt 940: ktrcsw(struct ktr_csw *cs)
1.1 deraadt 941: {
942: (void)printf("%s %s\n", cs->out ? "stop" : "resume",
943: cs->user ? "user" : "kernel");
944: }
945:
1.55 otto 946:
947:
948: void
949: ktrsockaddr(struct sockaddr *sa)
950: {
951: /*
952: TODO: Support additional address families
953: #include <netnatm/natm.h>
954: struct sockaddr_natm *natm;
955: #include <netsmb/netbios.h>
956: struct sockaddr_nb *nb;
957: */
958: char addr[64];
959:
960: /*
961: * note: ktrstruct() has already verified that sa points to a
962: * buffer at least sizeof(struct sockaddr) bytes long and exactly
963: * sa->sa_len bytes long.
964: */
965: printf("struct sockaddr { ");
966: sockfamilyname(sa->sa_family);
967: printf(", ");
968:
969: #define check_sockaddr_len(n) \
970: if (sa_##n->s##n##_len < sizeof(struct sockaddr_##n)) { \
971: printf("invalid"); \
972: break; \
973: }
974:
975: switch(sa->sa_family) {
976: case AF_INET: {
977: struct sockaddr_in *sa_in;
978:
979: sa_in = (struct sockaddr_in *)sa;
980: check_sockaddr_len(in);
981: inet_ntop(AF_INET, &sa_in->sin_addr, addr, sizeof addr);
982: printf("%s:%u", addr, ntohs(sa_in->sin_port));
983: break;
984: }
985: case AF_INET6: {
986: struct sockaddr_in6 *sa_in6;
987:
988: sa_in6 = (struct sockaddr_in6 *)sa;
989: check_sockaddr_len(in6);
990: inet_ntop(AF_INET6, &sa_in6->sin6_addr, addr, sizeof addr);
991: printf("[%s]:%u", addr, htons(sa_in6->sin6_port));
992: break;
993: }
994: #ifdef IPX
995: case AF_IPX: {
996: struct sockaddr_ipx *sa_ipx;
997:
998: sa_ipx = (struct sockaddr_ipx *)sa;
999: check_sockaddr_len(ipx);
1000: /* XXX wish we had ipx_ntop */
1001: printf("%s", ipx_ntoa(sa_ipx->sipx_addr));
1002: break;
1003: }
1004: #endif
1005: case AF_UNIX: {
1006: struct sockaddr_un *sa_un;
1007:
1008: sa_un = (struct sockaddr_un *)sa;
1009: if (sa_un->sun_len <= sizeof(sa_un->sun_len) +
1010: sizeof(sa_un->sun_family)) {
1011: printf("invalid");
1012: break;
1013: }
1014: printf("\"%.*s\"", (int)(sa_un->sun_len -
1015: sizeof(sa_un->sun_len) - sizeof(sa_un->sun_family)),
1016: sa_un->sun_path);
1017: break;
1018: }
1019: default:
1020: printf("unknown address family");
1021: }
1022: printf(" }\n");
1023: }
1024:
1025: void
1026: ktrstat(struct stat *statp)
1027: {
1028: char mode[12], timestr[PATH_MAX + 4];
1029: struct passwd *pwd;
1030: struct group *grp;
1031: struct tm *tm;
1032:
1033: /*
1034: * note: ktrstruct() has already verified that statp points to a
1035: * buffer exactly sizeof(struct stat) bytes long.
1036: */
1037: printf("struct stat {");
1038: strmode(statp->st_mode, mode);
1039: printf("dev=%d, ino=%u, mode=%s, nlink=%u, ",
1040: statp->st_dev, statp->st_ino, mode, statp->st_nlink);
1041: if (resolv == 0 || (pwd = getpwuid(statp->st_uid)) == NULL)
1042: printf("uid=%u, ", statp->st_uid);
1043: else
1044: printf("uid=\"%s\", ", pwd->pw_name);
1045: if (resolv == 0 || (grp = getgrgid(statp->st_gid)) == NULL)
1046: printf("gid=%u, ", statp->st_gid);
1047: else
1048: printf("gid=\"%s\", ", grp->gr_name);
1049: printf("rdev=%d, ", statp->st_rdev);
1050: printf("atime=");
1051: if (resolv == 0)
1052: printf("%jd", (intmax_t)statp->st_atim.tv_sec);
1053: else {
1054: tm = localtime(&statp->st_atim.tv_sec);
1055: (void)strftime(timestr, sizeof(timestr), TIME_FORMAT, tm);
1056: printf("\"%s\"", timestr);
1057: }
1058: if (statp->st_atim.tv_nsec != 0)
1059: printf(".%09ld, ", statp->st_atim.tv_nsec);
1060: else
1061: printf(", ");
1062: printf("stime=");
1063: if (resolv == 0)
1064: printf("%jd", (intmax_t)statp->st_mtim.tv_sec);
1065: else {
1066: tm = localtime(&statp->st_mtim.tv_sec);
1067: (void)strftime(timestr, sizeof(timestr), TIME_FORMAT, tm);
1068: printf("\"%s\"", timestr);
1069: }
1070: if (statp->st_mtim.tv_nsec != 0)
1071: printf(".%09ld, ", statp->st_mtim.tv_nsec);
1072: else
1073: printf(", ");
1074: printf("ctime=");
1075: if (resolv == 0)
1076: printf("%jd", (intmax_t)statp->st_ctim.tv_sec);
1077: else {
1078: tm = localtime(&statp->st_ctim.tv_sec);
1079: (void)strftime(timestr, sizeof(timestr), TIME_FORMAT, tm);
1080: printf("\"%s\"", timestr);
1081: }
1082: if (statp->st_ctim.tv_nsec != 0)
1083: printf(".%09ld, ", statp->st_ctim.tv_nsec);
1084: else
1085: printf(", ");
1086: printf("size=%lld, blocks=%lld, blksize=%u, flags=0x%x, gen=0x%x",
1087: statp->st_size, statp->st_blocks, statp->st_blksize,
1088: statp->st_flags, statp->st_gen);
1089: printf(" }\n");
1090: }
1091:
1092: void
1093: ktrstruct(char *buf, size_t buflen)
1094: {
1095: char *name, *data;
1096: size_t namelen, datalen;
1097: int i;
1098: struct stat sb;
1099: struct sockaddr_storage ss;
1100:
1101: for (name = buf, namelen = 0; namelen < buflen && name[namelen] != '\0';
1102: ++namelen)
1103: /* nothing */;
1104: if (namelen == buflen)
1105: goto invalid;
1106: if (name[namelen] != '\0')
1107: goto invalid;
1108: data = buf + namelen + 1;
1109: datalen = buflen - namelen - 1;
1110: if (datalen == 0)
1111: goto invalid;
1112: /* sanity check */
1113: for (i = 0; i < namelen; ++i)
1114: if (!isalpha((unsigned char)name[i]))
1115: goto invalid;
1116: if (strcmp(name, "stat") == 0) {
1117: if (datalen != sizeof(struct stat))
1118: goto invalid;
1119: memcpy(&sb, data, datalen);
1120: ktrstat(&sb);
1121: } else if (strcmp(name, "sockaddr") == 0) {
1122: if (datalen > sizeof(ss))
1123: goto invalid;
1124: memcpy(&ss, data, datalen);
1125: if ((ss.ss_family != AF_UNIX &&
1126: datalen < sizeof(struct sockaddr)) || datalen != ss.ss_len)
1127: goto invalid;
1128: ktrsockaddr((struct sockaddr *)&ss);
1129: } else {
1.57 otto 1130: printf("unknown structure %s\n", name);
1.55 otto 1131: }
1132: return;
1133: invalid:
1134: printf("invalid record\n");
1135: }
1136:
1.12 espie 1137: static void
1.17 deraadt 1138: usage(void)
1.1 deraadt 1139: {
1140:
1.19 mickey 1141: extern char *__progname;
1142: fprintf(stderr, "usage: %s "
1.55 otto 1143: "[-dlnRrTXx] [-e emulation] [-f file] [-m maxdata] [-p pid]\n"
1.40 sobrado 1144: "%*s[-t [ceinsw]]\n",
1.51 otto 1145: __progname, (int)(sizeof("usage: ") + strlen(__progname)), "");
1.1 deraadt 1146: exit(1);
1147: }
1148:
1.12 espie 1149: static void
1.17 deraadt 1150: setemul(const char *name)
1.1 deraadt 1151: {
1152: int i;
1.17 deraadt 1153:
1.1 deraadt 1154: for (i = 0; emulations[i].name != NULL; i++)
1155: if (strcmp(emulations[i].name, name) == 0) {
1156: current = &emulations[i];
1157: return;
1158: }
1159: warnx("Emulation `%s' unknown", name);
1160: }