kdump.c revision 1.112 1 /* $NetBSD: kdump.c,v 1.112 2011/06/01 21:28:32 alnsn Exp $ */
2
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. Neither the name of the University nor the names of its contributors
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/cdefs.h>
33 #ifndef lint
34 __COPYRIGHT("@(#) Copyright (c) 1988, 1993\
35 The Regents of the University of California. All rights reserved.");
36 #endif /* not lint */
37
38 #ifndef lint
39 #if 0
40 static char sccsid[] = "@(#)kdump.c 8.4 (Berkeley) 4/28/95";
41 #else
42 __RCSID("$NetBSD: kdump.c,v 1.112 2011/06/01 21:28:32 alnsn Exp $");
43 #endif
44 #endif /* not lint */
45
46 #include <sys/param.h>
47 #include <sys/proc.h> /* XXX #include <sys/file.h> fails without this header */
48 #define _KERNEL
49 #include <sys/file.h>
50 #include <sys/errno.h>
51 #undef _KERNEL
52 #include <sys/time.h>
53 #include <sys/uio.h>
54 #include <sys/ktrace.h>
55 #include <sys/ioctl.h>
56 #include <sys/ptrace.h>
57
58 #include <ctype.h>
59 #include <err.h>
60 #include <signal.h>
61 #include <stddef.h>
62 #include <stdio.h>
63 #include <stdlib.h>
64 #include <string.h>
65 #include <unistd.h>
66 #include <vis.h>
67
68 #include "ktrace.h"
69 #include "setemul.h"
70
71 #include <sys/syscall.h>
72
73 static int timestamp, decimal, plain, tail, maxdata = -1, numeric;
74 static int word_size = 0;
75 static pid_t do_pid = -1;
76 static const char *tracefile = NULL;
77 static struct ktr_header ktr_header;
78 static int emul_changed = 0;
79
80 #define eqs(s1, s2) (strcmp((s1), (s2)) == 0)
81 #define small(v) (((long)(v) >= 0) && ((long)(v) < 10))
82
83 static const char * const ptrace_ops[] = {
84 "PT_TRACE_ME", "PT_READ_I", "PT_READ_D", "PT_READ_U",
85 "PT_WRITE_I", "PT_WRITE_D", "PT_WRITE_U", "PT_CONTINUE",
86 "PT_KILL", "PT_ATTACH", "PT_DETACH", "PT_IO",
87 "PT_DUMPCORE", "PT_LWPINFO", "PT_SYSCALL",
88 };
89
90 #ifdef PT_MACHDEP_STRINGS
91 static const char * const ptrace_machdep_ops[] = { PT_MACHDEP_STRINGS };
92 #endif
93
94 static const char * const linux_ptrace_ops[] = {
95 "PTRACE_TRACEME",
96 "PTRACE_PEEKTEXT", "PTRACE_PEEKDATA", "PTRACE_PEEKUSER",
97 "PTRACE_POKETEXT", "PTRACE_POKEDATA", "PTRACE_POKEUSER",
98 "PTRACE_CONT", "PTRACE_KILL", "PTRACE_SINGLESTEP",
99 NULL, NULL,
100 "PTRACE_GETREGS", "PTRACE_SETREGS", "PTRACE_GETFPREGS",
101 "PTRACE_SETFPREGS", "PTRACE_ATTACH", "PTRACE_DETACH",
102 NULL, NULL, NULL, NULL, NULL, NULL,
103 "PTRACE_SYSCALL",
104 };
105
106 int main(int, char **);
107 static int fread_tail(void *, size_t, size_t);
108 static int dumpheader(struct ktr_header *);
109 static void output_long(u_long, int);
110 static void ioctldecode(u_long);
111 static void ktrsyscall(struct ktr_syscall *);
112 static void ktrsysret(struct ktr_sysret *, int);
113 static void ktrnamei(char *, int);
114 static void ktremul(char *, int, int);
115 static void ktrgenio(struct ktr_genio *, int);
116 static void ktrpsig(void *, int);
117 static void ktrcsw(struct ktr_csw *);
118 static void ktruser(struct ktr_user *, int);
119 static void ktrmib(int *, int);
120 static void ktrexecfd(struct ktr_execfd *);
121 static void usage(void) __dead;
122 static void eprint(int);
123 static void rprint(register_t);
124 static const char *signame(long, int);
125 static void hexdump_buf(const void *, int, int);
126 static void visdump_buf(const void *, int, int);
127
128 int
129 main(int argc, char **argv)
130 {
131 int ch, ktrlen, size;
132 void *m;
133 int trpoints = 0;
134 int trset = 0;
135 const char *emul_name = "netbsd";
136 int col;
137 char *cp;
138
139 setprogname(argv[0]);
140
141 if (strcmp(getprogname(), "ioctlname") == 0) {
142 int i;
143
144 while ((ch = getopt(argc, argv, "e:")) != -1)
145 switch (ch) {
146 case 'e':
147 emul_name = optarg;
148 break;
149 default:
150 usage();
151 break;
152 }
153 setemul(emul_name, 0, 0);
154 argv += optind;
155 argc -= optind;
156
157 if (argc < 1)
158 usage();
159
160 for (i = 0; i < argc; i++) {
161 ioctldecode(strtoul(argv[i], NULL, 0));
162 (void)putchar('\n');
163 }
164 return 0;
165 }
166
167 while ((ch = getopt(argc, argv, "e:f:dlm:Nnp:RTt:xX:")) != -1) {
168 switch (ch) {
169 case 'e':
170 emul_name = strdup(optarg); /* it's safer to copy it */
171 break;
172 case 'f':
173 tracefile = optarg;
174 break;
175 case 'd':
176 decimal = 1;
177 break;
178 case 'l':
179 tail = 1;
180 break;
181 case 'p':
182 do_pid = strtoul(optarg, &cp, 0);
183 if (*cp != 0)
184 errx(1,"invalid number %s", optarg);
185 break;
186 case 'm':
187 maxdata = strtoul(optarg, &cp, 0);
188 if (*cp != 0)
189 errx(1,"invalid number %s", optarg);
190 break;
191 case 'N':
192 numeric++;
193 break;
194 case 'n':
195 plain++;
196 break;
197 case 'R':
198 timestamp = 2; /* relative timestamp */
199 break;
200 case 'T':
201 timestamp = 1;
202 break;
203 case 't':
204 trset = 1;
205 trpoints = getpoints(trpoints, optarg);
206 if (trpoints < 0)
207 errx(1, "unknown trace point in %s", optarg);
208 break;
209 case 'x':
210 word_size = 1;
211 break;
212 case 'X':
213 word_size = strtoul(optarg, &cp, 0);
214 if (*cp != 0 || word_size & (word_size - 1) ||
215 word_size > 16 || word_size <= 0)
216 errx(1, "argument to -X must be "
217 "1, 2, 4, 8 or 16");
218 break;
219 default:
220 usage();
221 }
222 }
223 argv += optind;
224 argc -= optind;
225
226 if (!trset)
227 trpoints = ALL_POINTS;
228
229 if (tracefile == NULL) {
230 if (argc == 1) {
231 tracefile = argv[0];
232 argv++;
233 argc--;
234 } else
235 tracefile = DEF_TRACEFILE;
236 }
237
238 if (argc > 0)
239 usage();
240
241 setemul(emul_name, 0, 0);
242
243 m = malloc(size = 1024);
244 if (m == NULL)
245 errx(1, "malloc: %s", strerror(ENOMEM));
246 if (!freopen(tracefile, "r", stdin))
247 err(1, "%s", tracefile);
248 while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) {
249 if (trpoints & (1 << ktr_header.ktr_type) &&
250 (do_pid == -1 || ktr_header.ktr_pid == do_pid))
251 col = dumpheader(&ktr_header);
252 else
253 col = -1;
254 if ((ktrlen = ktr_header.ktr_len) < 0)
255 errx(1, "bogus length 0x%x", ktrlen);
256 if (ktrlen > size) {
257 while (ktrlen > size)
258 size *= 2;
259 m = realloc(m, size);
260 if (m == NULL)
261 errx(1, "realloc: %s", strerror(ENOMEM));
262 }
263 if (ktrlen && fread_tail(m, ktrlen, 1) == 0)
264 errx(1, "data too short");
265 if (col == -1)
266 continue;
267
268 /* update context to match currently processed record */
269 ectx_sanify(ktr_header.ktr_pid);
270
271 switch (ktr_header.ktr_type) {
272 case KTR_SYSCALL:
273 ktrsyscall(m);
274 break;
275 case KTR_SYSRET:
276 ktrsysret(m, ktrlen);
277 break;
278 case KTR_NAMEI:
279 ktrnamei(m, ktrlen);
280 break;
281 case KTR_GENIO:
282 ktrgenio(m, ktrlen);
283 break;
284 case KTR_PSIG:
285 ktrpsig(m, ktrlen);
286 break;
287 case KTR_CSW:
288 ktrcsw(m);
289 break;
290 case KTR_EMUL:
291 ktremul(m, ktrlen, size);
292 break;
293 case KTR_USER:
294 ktruser(m, ktrlen);
295 break;
296 case KTR_EXEC_ARG:
297 case KTR_EXEC_ENV:
298 visdump_buf(m, ktrlen, col);
299 break;
300 case KTR_EXEC_FD:
301 ktrexecfd(m);
302 break;
303 case KTR_MIB:
304 ktrmib(m, ktrlen);
305 break;
306 default:
307 putchar('\n');
308 hexdump_buf(m, ktrlen, word_size ? word_size : 1);
309 }
310 if (tail)
311 (void)fflush(stdout);
312 }
313 return (0);
314 }
315
316 static int
317 fread_tail(void *buf, size_t num, size_t size)
318 {
319 int i;
320
321 while ((i = fread(buf, size, num, stdin)) == 0 && tail) {
322 (void)sleep(1);
323 clearerr(stdin);
324 }
325 return (i);
326 }
327
328 static int
329 dumpheader(struct ktr_header *kth)
330 {
331 char unknown[64];
332 const char *type;
333 union holdtime {
334 struct timeval tv;
335 struct timespec ts;
336 };
337 static union holdtime prevtime;
338 union holdtime temp;
339 int col;
340
341 switch (kth->ktr_type) {
342 case KTR_SYSCALL:
343 type = "CALL";
344 break;
345 case KTR_SYSRET:
346 type = "RET ";
347 break;
348 case KTR_NAMEI:
349 type = "NAMI";
350 break;
351 case KTR_GENIO:
352 type = "GIO ";
353 break;
354 case KTR_PSIG:
355 type = "PSIG";
356 break;
357 case KTR_CSW:
358 type = "CSW ";
359 break;
360 case KTR_EMUL:
361 type = "EMUL";
362 break;
363 case KTR_USER:
364 type = "MISC";
365 break;
366 case KTR_EXEC_ENV:
367 type = "ENV";
368 break;
369 case KTR_EXEC_ARG:
370 type = "ARG";
371 break;
372 case KTR_EXEC_FD:
373 type = "FD";
374 break;
375 case KTR_SAUPCALL:
376 type = "SAU";
377 break;
378 case KTR_MIB:
379 type = "MIB";
380 break;
381 default:
382 (void)snprintf(unknown, sizeof(unknown), "UNKNOWN(%d)",
383 kth->ktr_type);
384 type = unknown;
385 }
386
387 col = printf("%6d ", kth->ktr_pid);
388 if (kth->ktr_version > KTRFACv0)
389 col += printf("%6d ", kth->ktr_lid);
390 col += printf("%-8.*s ", MAXCOMLEN, kth->ktr_comm);
391 if (timestamp) {
392 (void)&prevtime;
393 if (timestamp == 2) {
394 switch (kth->ktr_version) {
395 case KTRFAC_VERSION(KTRFACv0):
396 if (prevtime.tv.tv_sec == 0)
397 temp.tv.tv_sec = temp.tv.tv_usec = 0;
398 else
399 timersub(&kth->ktr_otv,
400 &prevtime.tv, &temp.tv);
401 prevtime.tv.tv_sec = kth->ktr_otv.tv_sec;
402 prevtime.tv.tv_usec = kth->ktr_otv.tv_usec;
403 break;
404 case KTRFAC_VERSION(KTRFACv1):
405 if (prevtime.ts.tv_sec == 0)
406 temp.ts.tv_sec = temp.ts.tv_nsec = 0;
407 else
408 timespecsub(&kth->ktr_ots,
409 &prevtime.ts, &temp.ts);
410 prevtime.ts.tv_sec = kth->ktr_ots.tv_sec;
411 prevtime.ts.tv_nsec = kth->ktr_ots.tv_nsec;
412 break;
413 case KTRFAC_VERSION(KTRFACv2):
414 if (prevtime.ts.tv_sec == 0)
415 temp.ts.tv_sec = temp.ts.tv_nsec = 0;
416 else
417 timespecsub(&kth->ktr_ts,
418 &prevtime.ts, &temp.ts);
419 prevtime.ts.tv_sec = kth->ktr_ts.tv_sec;
420 prevtime.ts.tv_nsec = kth->ktr_ts.tv_nsec;
421 break;
422 default:
423 goto badversion;
424 }
425 } else {
426 switch (kth->ktr_version) {
427 case KTRFAC_VERSION(KTRFACv0):
428 temp.tv.tv_sec = kth->ktr_otv.tv_sec;
429 temp.tv.tv_usec = kth->ktr_otv.tv_usec;
430 break;
431 case KTRFAC_VERSION(KTRFACv1):
432 temp.ts.tv_sec = kth->ktr_ots.tv_sec;
433 temp.ts.tv_nsec = kth->ktr_ots.tv_nsec;
434 break;
435 case KTRFAC_VERSION(KTRFACv2):
436 temp.ts.tv_sec = kth->ktr_ts.tv_sec;
437 temp.ts.tv_nsec = kth->ktr_ts.tv_nsec;
438 break;
439 default:
440 badversion:
441 err(1, "Unsupported ktrace version %x\n",
442 kth->ktr_version);
443 }
444 }
445 if (kth->ktr_version == KTRFACv0)
446 col += printf("%lld.%06ld ",
447 (long long)temp.tv.tv_sec, (long)temp.tv.tv_usec);
448 else
449 col += printf("%lld.%09ld ",
450 (long long)temp.ts.tv_sec, (long)temp.ts.tv_nsec);
451 }
452 col += printf("%-4s ", type);
453 return col;
454 }
455
456 static void
457 output_long(u_long it, int as_x)
458 {
459 if (cur_emul->flags & EMUL_FLAG_NETBSD32)
460 printf(as_x ? "%#x" : "%d", (u_int)it);
461 else
462 printf(as_x ? "%#lx" : "%ld", it);
463 }
464
465 static void
466 ioctldecode(u_long cmd)
467 {
468 char dirbuf[4], *dir = dirbuf;
469 int c;
470
471 if (cmd & IOC_IN)
472 *dir++ = 'W';
473 if (cmd & IOC_OUT)
474 *dir++ = 'R';
475 *dir = '\0';
476
477 c = (cmd >> 8) & 0xff;
478 if (isprint(c))
479 printf("_IO%s('%c',", dirbuf, c);
480 else
481 printf("_IO%s(0x%02x,", dirbuf, c);
482 output_long(cmd & 0xff, decimal == 0);
483 if ((cmd & IOC_VOID) == 0) {
484 putchar(',');
485 output_long(IOCPARM_LEN(cmd), decimal == 0);
486 }
487 putchar(')');
488 }
489
490 static void
491 ktrsyscall(struct ktr_syscall *ktr)
492 {
493 int argcount;
494 const struct emulation *emul = cur_emul;
495 register_t *ap;
496 char c;
497 const char *cp;
498 const char *sys_name;
499
500 argcount = ktr->ktr_argsize / sizeof (*ap);
501
502 emul_changed = 0;
503
504 if (numeric ||
505 ((ktr->ktr_code >= emul->nsysnames || ktr->ktr_code < 0))) {
506 sys_name = "?";
507 (void)printf("[%d]", ktr->ktr_code);
508 } else {
509 sys_name = emul->sysnames[ktr->ktr_code];
510 (void)printf("%s", sys_name);
511 }
512 #ifdef _LP64
513 #define NETBSD32_ "netbsd32_"
514 if (cur_emul->flags & EMUL_FLAG_NETBSD32) {
515 size_t len = strlen(NETBSD32_);
516 if (strncmp(sys_name, NETBSD32_, len) == 0)
517 sys_name += len;
518 }
519 #undef NETBSD32_
520 #endif
521
522 ap = (register_t *)((char *)ktr + sizeof(struct ktr_syscall));
523 if (argcount) {
524 c = '(';
525 if (plain) {
526 ;
527
528 } else if (strcmp(sys_name, "exit_group") == 0 ||
529 (strcmp(emul->name, "linux") != 0 &&
530 strcmp(emul->name, "linux32") != 0 &&
531 strcmp(sys_name, "exit") == 0)) {
532 ectx_delete();
533
534 } else if (strcmp(sys_name, "ioctl") == 0 && argcount >= 2) {
535 (void)putchar('(');
536 output_long((long)*ap, !(decimal || small(*ap)));
537 ap++;
538 argcount--;
539 if ((cp = ioctlname(*ap)) != NULL)
540 (void)printf(",%s", cp);
541 else {
542 (void)putchar(',');
543 ioctldecode(*ap);
544 }
545 ap++;
546 argcount--;
547 c = ',';
548
549 } else if ((strstr(sys_name, "sigaction") != NULL ||
550 strstr(sys_name, "sigvec") != NULL) && argcount >= 1) {
551 (void)printf("(SIG%s", signame(ap[0], 1));
552 ap += 1;
553 argcount -= 1;
554 c = ',';
555
556 } else if ((strcmp(sys_name, "kill") == 0 ||
557 strcmp(sys_name, "killpg") == 0) && argcount >= 2) {
558 putchar('(');
559 output_long((long)ap[0], !(decimal || small(*ap)));
560 (void)printf(", SIG%s", signame(ap[1], 1));
561 ap += 2;
562 argcount -= 2;
563 c = ',';
564
565 } else if (strcmp(sys_name, "ptrace") == 0 && argcount >= 1) {
566 putchar('(');
567 if (strcmp(emul->name, "linux") == 0 ||
568 strcmp(emul->name, "linux32") == 0) {
569 if ((long)*ap >= 0 && *ap <
570 (register_t)(sizeof(linux_ptrace_ops) /
571 sizeof(linux_ptrace_ops[0])))
572 (void)printf("%s",
573 linux_ptrace_ops[*ap]);
574 else
575 output_long((long)*ap, 1);
576 } else {
577 if ((long)*ap >= 0 && *ap <
578 (register_t)(sizeof(ptrace_ops) / sizeof(ptrace_ops[0])))
579 (void)printf("%s", ptrace_ops[*ap]);
580 #ifdef PT_MACHDEP_STRINGS
581 else if (*ap >= PT_FIRSTMACH &&
582 *ap - PT_FIRSTMACH <
583 (register_t)(sizeof(ptrace_machdep_ops) /
584 sizeof(ptrace_machdep_ops[0])))
585 (void)printf("%s", ptrace_machdep_ops[*ap - PT_FIRSTMACH]);
586 #endif
587 else
588 output_long((long)*ap, 1);
589 }
590 ap++;
591 argcount--;
592 c = ',';
593
594 }
595 while (argcount > 0) {
596 putchar(c);
597 output_long((long)*ap, !(decimal || small(*ap)));
598 ap++;
599 argcount--;
600 c = ',';
601 }
602 (void)putchar(')');
603 }
604 (void)putchar('\n');
605 }
606
607 static void
608 ktrsysret(struct ktr_sysret *ktr, int len)
609 {
610 const struct emulation *emul;
611 int error = ktr->ktr_error;
612 int code = ktr->ktr_code;
613
614 if (emul_changed) {
615 /* In order to get system call name right in execve return */
616 emul = prev_emul;
617 emul_changed = 0;
618 } else
619 emul = cur_emul;
620
621 if (numeric || ((code >= emul->nsysnames || code < 0 || plain > 1)))
622 (void)printf("[%d] ", code);
623 else
624 (void)printf("%s ", emul->sysnames[code]);
625
626 switch (error) {
627 case 0:
628 rprint(ktr->ktr_retval);
629 if (len > (int)offsetof(struct ktr_sysret, ktr_retval_1) &&
630 ktr->ktr_retval_1 != 0) {
631 (void)printf(", ");
632 rprint(ktr->ktr_retval_1);
633 }
634 break;
635
636 default:
637 eprint(error);
638 break;
639 }
640 (void)putchar('\n');
641 }
642
643 static void
644 ktrexecfd(struct ktr_execfd *ktr)
645 {
646 static const char *dnames[] = { DTYPE_NAMES };
647 if (ktr->ktr_dtype < __arraycount(dnames))
648 printf("%s %d\n", dnames[ktr->ktr_dtype], ktr->ktr_fd);
649 else
650 printf("UNKNOWN(%u) %d\n", ktr->ktr_dtype, ktr->ktr_fd);
651 }
652
653 static void
654 rprint(register_t ret)
655 {
656
657 if (!plain) {
658 (void)printf("%ld", (long)ret);
659 if (!small(ret))
660 (void)printf("/%#lx", (long)ret);
661 } else {
662 if (decimal || small(ret))
663 (void)printf("%ld", (long)ret);
664 else
665 (void)printf("%#lx", (long)ret);
666 }
667 }
668
669 /*
670 * We print the original emulation's error numerically, but we
671 * translate it to netbsd to print it symbolically.
672 */
673 static void
674 eprint(int e)
675 {
676 int i = e;
677
678 if (cur_emul->errnomap) {
679
680 /* No remapping for ERESTART and EJUSTRETURN */
681 /* Kludge for linux that has negative error numbers */
682 if (cur_emul->errnomap[2] > 0 && e < 0)
683 goto normal;
684
685 for (i = 0; i < cur_emul->nerrnomap; i++)
686 if (e == cur_emul->errnomap[i])
687 break;
688
689 if (i == cur_emul->nerrnomap) {
690 printf("-1 unknown errno %d", e);
691 return;
692 }
693 }
694
695 normal:
696 switch (i) {
697 case ERESTART:
698 (void)printf("RESTART");
699 break;
700
701 case EJUSTRETURN:
702 (void)printf("JUSTRETURN");
703 break;
704
705 default:
706 (void)printf("-1 errno %d", e);
707 if (!plain)
708 (void)printf(" %s", strerror(i));
709 }
710 }
711
712 static void
713 ktrnamei(char *cp, int len)
714 {
715
716 (void)printf("\"%.*s\"\n", len, cp);
717 }
718
719 static void
720 ktremul(char *name, int len, int bufsize)
721 {
722
723 if (len >= bufsize)
724 len = bufsize - 1;
725
726 name[len] = '\0';
727 setemul(name, ktr_header.ktr_pid, 1);
728 emul_changed = 1;
729
730 (void)printf("\"%s\"\n", name);
731 }
732
733 static void
734 hexdump_buf(const void *vdp, int datalen, int word_sz)
735 {
736 const char hex[] = "0123456789abcdef";
737 char chars[16], prev[16];
738 char bytes[16 * 3 + 4];
739 const unsigned char *dp = vdp;
740 const unsigned char *datalim = dp + datalen;
741 const unsigned char *line_end;
742 int off, l = 0, c;
743 char *cp, *bp;
744 int divmask = word_sz - 1; /* block size in bytes */
745 int gdelim = 3; /* gap between blocks */
746 int bsize = 2; /* increment for each byte */
747 int width;
748 int dupl = 0;
749 #if _BYTE_ORDER == _LITTLE_ENDIAN
750 int bswap = word_sz - 1;
751 #else
752 #define bswap 0
753 #endif
754
755 switch (word_sz) {
756 case 2:
757 gdelim = 2;
758 break;
759 case 1:
760 divmask = 7;
761 bsize = 3;
762 gdelim = 1;
763 break;
764 default:
765 break;
766 }
767 width = 16 * bsize + (16 / (divmask + 1)) * gdelim;
768 if (word_sz != 1)
769 width += 2;
770
771 for (off = 0; dp < datalim; off += l) {
772 memset(bytes, ' ', sizeof bytes);
773 line_end = dp + 16;
774 if (line_end >= datalim) {
775 line_end = datalim;
776 dupl |= 1; /* need to print */
777 } else {
778 if (dupl == 0 || memcmp(dp, prev, sizeof chars))
779 dupl |= 1;
780 }
781
782 if (!(dupl & 1)) {
783 /* This is a duplicate of the line above, count 'em */
784 dupl += 2;
785 dp = line_end;
786 continue;
787 }
788
789 if (dupl > 3) {
790 /* previous line as a duplicate */
791 if (dupl == 5)
792 /* Only one duplicate, print line */
793 printf("\t%-5.3x%.*s%.*s\n",
794 off - l, width, bytes, l, chars);
795 else
796 printf("\t%.*s\n",
797 snprintf(NULL, 0, "%3x", off), "*****");
798 }
799
800 for (l = 0, bp = bytes, cp = chars; dp < line_end; l++) {
801 c = *dp++;
802 prev[l] = c;
803 if ((l & divmask) == 0)
804 bp += gdelim;
805 bp[(l ^ bswap) * bsize] = hex[c >> 4];
806 bp[(l ^ bswap) * bsize + 1] = hex[c & 0xf];
807 *cp++ = isgraph(c) ? c : '.';
808 }
809
810 printf("\t%-5.3x%.*s%.*s\n", off, width, bytes, l, chars);
811 dupl = 2;
812 }
813 }
814
815 static void
816 visdump_buf(const void *vdp, int datalen, int col)
817 {
818 const unsigned char *dp = vdp;
819 char *cp;
820 int width;
821 char visbuf[5];
822 static int screenwidth = 0;
823
824 if (screenwidth == 0) {
825 struct winsize ws;
826
827 if (!plain && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 &&
828 ws.ws_col > 8)
829 screenwidth = ws.ws_col;
830 else
831 screenwidth = 80;
832 }
833
834 (void)printf("\"");
835 col++;
836 for (; datalen > 0; datalen--, dp++) {
837 (void)svis(visbuf, *dp, VIS_CSTYLE,
838 datalen > 1 ? *(dp + 1) : 0, "\"\n");
839 cp = visbuf;
840 /*
841 * Keep track of printables and
842 * space chars (like fold(1)).
843 */
844 if (col == 0) {
845 (void)putchar('\t');
846 col = 8;
847 }
848 switch (*cp) {
849 case '\n':
850 col = 0;
851 (void)putchar('\n');
852 continue;
853 case '\t':
854 width = 8 - (col & 07);
855 break;
856 default:
857 width = strlen(cp);
858 }
859 if (col + width > (screenwidth - 2)) {
860 (void)printf("\\\n\t");
861 col = 8;
862 if (*cp == '\t')
863 width = 8;
864 }
865 col += width;
866 do {
867 (void)putchar(*cp++);
868 } while (*cp);
869 }
870 if (col == 0)
871 (void)printf(" ");
872 (void)printf("\"\n");
873 }
874
875 static void
876 ktrgenio(struct ktr_genio *ktr, int len)
877 {
878 int datalen = len - sizeof (struct ktr_genio);
879 char *dp = (char *)ktr + sizeof (struct ktr_genio);
880
881 if (ktr->ktr_fd != -1)
882 printf("fd %d ", ktr->ktr_fd);
883 printf("%s %d bytes\n",
884 ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen);
885 if (maxdata == 0)
886 return;
887 if (maxdata > 0 && datalen > maxdata)
888 datalen = maxdata;
889 if (word_size) {
890 hexdump_buf(dp, datalen, word_size);
891 return;
892 }
893 (void)printf(" ");
894 visdump_buf(dp, datalen, 7);
895 }
896
897 static void
898 ktrpsig(void *v, int len)
899 {
900 int signo, first;
901 struct {
902 struct ktr_psig ps;
903 siginfo_t si;
904 } *psig = v;
905 siginfo_t *si = &psig->si;
906 const char *code;
907
908 (void)printf("SIG%s ", signame(psig->ps.signo, 0));
909 if (psig->ps.action == SIG_DFL)
910 (void)printf("SIG_DFL");
911 else {
912 (void)printf("caught handler=%p mask=(", psig->ps.action);
913 first = 1;
914 for (signo = 1; signo < NSIG; signo++) {
915 if (sigismember(&psig->ps.mask, signo)) {
916 if (first)
917 first = 0;
918 else
919 (void)printf(",");
920 (void)printf("%d", signo);
921 }
922 }
923 (void)printf(")");
924 }
925 switch (len) {
926 case sizeof(struct ktr_psig):
927 if (psig->ps.code)
928 printf(" code=0x%x", psig->ps.code);
929 printf(psig->ps.action == SIG_DFL ? "\n" : ")\n");
930 return;
931 case sizeof(*psig):
932 if (si->si_code == 0) {
933 printf(": code=SI_USER sent by pid=%d, uid=%d)\n",
934 si->si_pid, si->si_uid);
935 return;
936 }
937
938 if (si->si_code < 0) {
939 switch (si->si_code) {
940 case SI_TIMER:
941 case SI_QUEUE:
942 printf(": code=%s sent by pid=%d, uid=%d with "
943 "sigval %p)\n", si->si_code == SI_TIMER ?
944 "SI_TIMER" : "SI_QUEUE", si->si_pid,
945 si->si_uid, si->si_value.sival_ptr);
946 return;
947 case SI_ASYNCIO:
948 case SI_MESGQ:
949 printf(": code=%s with sigval %p)\n",
950 si->si_code == SI_ASYNCIO ?
951 "SI_ASYNCIO" : "SI_MESGQ",
952 si->si_value.sival_ptr);
953 return;
954 case SI_LWP:
955 printf(": code=SI_LWP sent by pid=%d, "
956 "uid=%d)\n", si->si_pid, si->si_uid);
957 return;
958 default:
959 code = NULL;
960 break;
961 }
962 if (code)
963 printf(": code=%s unimplemented)\n", code);
964 else
965 printf(": code=%d unimplemented)\n",
966 si->si_code);
967 return;
968 }
969
970 if (si->si_code == SI_NOINFO) {
971 printf(": code=SI_NOINFO\n");
972 return;
973 }
974
975 code = siginfocodename(si->si_signo, si->si_code);
976 switch (si->si_signo) {
977 case SIGCHLD:
978 printf(": code=%s child pid=%d, uid=%d, "
979 " status=%u, utime=%lu, stime=%lu)\n",
980 code, si->si_pid,
981 si->si_uid, si->si_status,
982 (unsigned long) si->si_utime,
983 (unsigned long) si->si_stime);
984 return;
985 case SIGILL:
986 case SIGFPE:
987 case SIGSEGV:
988 case SIGBUS:
989 case SIGTRAP:
990 printf(": code=%s, addr=%p, trap=%d)\n",
991 code, si->si_addr, si->si_trap);
992 return;
993 case SIGIO:
994 printf(": code=%s, fd=%d, band=%lx)\n",
995 code, si->si_fd, si->si_band);
996 return;
997 default:
998 printf(": code=%s, errno=%d)\n",
999 code, si->si_errno);
1000 return;
1001 }
1002 /*NOTREACHED*/
1003 default:
1004 warnx("Unhandled size %d for ktrpsig\n", len);
1005 break;
1006 }
1007 }
1008
1009 static void
1010 ktrcsw(struct ktr_csw *cs)
1011 {
1012
1013 (void)printf("%s %s\n", cs->out ? "stop" : "resume",
1014 cs->user ? "user" : "kernel");
1015 }
1016
1017 static void
1018 ktruser(struct ktr_user *usr, int len)
1019 {
1020 int i;
1021 unsigned char *dta;
1022
1023 len -= sizeof(struct ktr_user);
1024 printf("%.*s:", KTR_USER_MAXIDLEN, usr->ktr_id);
1025 dta = (unsigned char *)(usr + 1);
1026 if (word_size) {
1027 printf("\n");
1028 hexdump_buf(dta, len, word_size);
1029 return;
1030 }
1031 printf(" %d, ", len);
1032 for (i = 0; i < len; i++)
1033 printf("%02x", (unsigned int) dta[i]);
1034 printf("\n");
1035 }
1036
1037 static void
1038 ktrmib(int *namep, int len)
1039 {
1040 size_t i;
1041
1042 for (i = 0; i < (len / sizeof(*namep)); i++)
1043 printf("%s%d", (i == 0) ? "" : ".", namep[i]);
1044 printf("\n");
1045 }
1046
1047 static const char *
1048 signame(long sig, int xlat)
1049 {
1050 static char buf[64];
1051
1052 if (sig == 0)
1053 return " 0";
1054 else if (sig < 0 || sig >= NSIG) {
1055 (void)snprintf(buf, sizeof(buf), "*unknown %ld*", sig);
1056 return buf;
1057 } else
1058 return sys_signame[(xlat && cur_emul->signalmap != NULL) ?
1059 cur_emul->signalmap[sig] : sig];
1060 }
1061
1062 static void
1063 usage(void)
1064 {
1065 if (strcmp(getprogname(), "ioctlname") == 0) {
1066 (void)fprintf(stderr, "Usage: %s [-e emulation] <ioctl> ...\n",
1067 getprogname());
1068 } else {
1069 (void)fprintf(stderr, "Usage: %s [-dlNnRT] [-e emulation] "
1070 "[-f file] [-m maxdata] [-p pid]\n [-t trstr] "
1071 "[-x | -X size] [file]\n", getprogname());
1072 }
1073 exit(1);
1074 }
1075