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