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