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