1 /*- 2 * Copyright (c) 1988, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#) Copyright (c) 1988, 1993 The Regents of the University of California. All rights reserved. 34 * @(#)kdump.c 8.1 (Berkeley) 6/6/93 35 * $FreeBSD: src/usr.bin/kdump/kdump.c,v 1.29 2006/05/20 14:27:22 netchild Exp $ 36 * $DragonFly: src/usr.bin/kdump/kdump.c,v 1.13 2008/10/16 01:52:32 swildner Exp $ 37 */ 38 39 #define _KERNEL_STRUCTURES 40 41 #include <sys/errno.h> 42 #include <sys/param.h> 43 #include <sys/errno.h> 44 #include <sys/time.h> 45 #include <sys/uio.h> 46 #include <sys/ktrace.h> 47 #include <sys/ioctl.h> 48 #include <sys/ptrace.h> 49 #include <err.h> 50 #include <locale.h> 51 #include <stdio.h> 52 #include <stdlib.h> 53 #include <string.h> 54 #include <unistd.h> 55 #include <vis.h> 56 #include "ktrace.h" 57 #include "kdump_subr.h" 58 59 extern const char *ioctlname(u_long); 60 61 static int dumpheader(struct ktr_header *); 62 static int fread_tail(void *, int, int); 63 static void ktrcsw(struct ktr_csw *); 64 static void ktrgenio(struct ktr_genio *, int); 65 static void ktrnamei(char *, int); 66 static void ktrpsig(struct ktr_psig *); 67 static void ktrsyscall(struct ktr_syscall *); 68 static void ktrsysret(struct ktr_sysret *); 69 static void ktruser(int, unsigned char *); 70 static void ktruser_malloc(int, unsigned char *); 71 static void timevalfix(struct timeval *); 72 static void timevalsub(struct timeval *, struct timeval *); 73 static void usage(void); 74 75 int timestamp, decimal, fancy = 1, tail, maxdata = 64; 76 int fixedformat; 77 const char *tracefile = DEF_TRACEFILE; 78 struct ktr_header ktr_header; 79 80 #define eqs(s1, s2) (strcmp((s1), (s2)) == 0) 81 82 int 83 main(int argc, char **argv) 84 { 85 int ch, col, ktrlen, size; 86 pid_t do_pid = -1; 87 void *m; 88 int trpoints = ALL_POINTS; 89 char *cp; 90 91 (void) setlocale(LC_CTYPE, ""); 92 93 while ((ch = getopt(argc,argv,"f:djlm:np:RTt:")) != -1) 94 switch((char)ch) { 95 case 'f': 96 tracefile = optarg; 97 break; 98 case 'j': 99 fixedformat = 1; 100 break; 101 case 'd': 102 decimal = 1; 103 break; 104 case 'l': 105 tail = 1; 106 break; 107 case 'm': 108 maxdata = atoi(optarg); 109 break; 110 case 'n': 111 fancy = 0; 112 break; 113 case 'p': 114 do_pid = strtoul(optarg, &cp, 0); 115 if (*cp != 0) 116 errx(1,"invalid number %s", optarg); 117 break; 118 case 'R': 119 timestamp = 2; /* relative timestamp */ 120 break; 121 case 'T': 122 timestamp = 1; 123 break; 124 case 't': 125 trpoints = getpoints(optarg); 126 if (trpoints < 0) 127 errx(1, "unknown trace point in %s", optarg); 128 break; 129 default: 130 usage(); 131 } 132 133 if (argc > optind) 134 usage(); 135 136 m = (void *)malloc(size = 1025); 137 if (m == NULL) 138 errx(1, "%s", strerror(ENOMEM)); 139 if (!freopen(tracefile, "r", stdin)) 140 err(1, "%s", tracefile); 141 while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) { 142 if (trpoints & (1 << ktr_header.ktr_type) && 143 (do_pid == -1 || ktr_header.ktr_pid == do_pid)) 144 col = dumpheader(&ktr_header); 145 else 146 col = -1; 147 if ((ktrlen = ktr_header.ktr_len) < 0) 148 errx(1, "bogus length 0x%x", ktrlen); 149 if (ktrlen > size) { 150 m = (void *)realloc(m, ktrlen+1); 151 if (m == NULL) 152 errx(1, "%s", strerror(ENOMEM)); 153 size = ktrlen; 154 } 155 if (ktrlen && fread_tail(m, ktrlen, 1) == 0) 156 errx(1, "data too short"); 157 if ((trpoints & (1<<ktr_header.ktr_type)) == 0) 158 continue; 159 if (col == -1) 160 continue; 161 switch (ktr_header.ktr_type) { 162 case KTR_SYSCALL: 163 ktrsyscall((struct ktr_syscall *)m); 164 break; 165 case KTR_SYSRET: 166 ktrsysret((struct ktr_sysret *)m); 167 break; 168 case KTR_NAMEI: 169 ktrnamei(m, ktrlen); 170 break; 171 case KTR_GENIO: 172 ktrgenio((struct ktr_genio *)m, ktrlen); 173 break; 174 case KTR_PSIG: 175 ktrpsig((struct ktr_psig *)m); 176 break; 177 case KTR_CSW: 178 ktrcsw((struct ktr_csw *)m); 179 break; 180 case KTR_USER: 181 ktruser(ktrlen, m); 182 break; 183 } 184 if (tail) 185 (void)fflush(stdout); 186 } 187 exit(0); 188 } 189 190 static int 191 fread_tail(void *buf, int size, int num) 192 { 193 int i; 194 195 while ((i = fread(buf, size, num, stdin)) == 0 && tail) { 196 (void)sleep(1); 197 clearerr(stdin); 198 } 199 return (i); 200 } 201 202 static int 203 dumpheader(struct ktr_header *kth) 204 { 205 static char unknown[64]; 206 static struct timeval prevtime, temp; 207 const char *type; 208 int col; 209 210 switch (kth->ktr_type) { 211 case KTR_SYSCALL: 212 type = "CALL"; 213 break; 214 case KTR_SYSRET: 215 type = "RET "; 216 break; 217 case KTR_NAMEI: 218 type = "NAMI"; 219 break; 220 case KTR_GENIO: 221 type = "GIO "; 222 break; 223 case KTR_PSIG: 224 type = "PSIG"; 225 break; 226 case KTR_CSW: 227 type = "CSW"; 228 break; 229 case KTR_USER: 230 type = "USER"; 231 break; 232 default: 233 (void)sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type); 234 type = unknown; 235 } 236 237 if (kth->ktr_tid || (kth->ktr_flags & KTRH_THREADED) || fixedformat) 238 col = printf("%5d:%-4d", kth->ktr_pid, kth->ktr_tid); 239 else 240 col = printf("%5d", kth->ktr_pid); 241 col += printf(" %-8.*s ", MAXCOMLEN, kth->ktr_comm); 242 if (timestamp) { 243 if (timestamp == 2) { 244 temp = kth->ktr_time; 245 timevalsub(&kth->ktr_time, &prevtime); 246 prevtime = temp; 247 } 248 col += printf("%ld.%06ld ", 249 kth->ktr_time.tv_sec, kth->ktr_time.tv_usec); 250 } 251 col += printf("%s ", type); 252 return col; 253 } 254 255 #include <sys/syscall.h> 256 #define KTRACE 257 #include <sys/kern/syscalls.c> 258 #undef KTRACE 259 int nsyscalls = sizeof (syscallnames) / sizeof (syscallnames[0]); 260 261 static const char *ptrace_ops[] = { 262 "PT_TRACE_ME", "PT_READ_I", "PT_READ_D", "PT_READ_U", 263 "PT_WRITE_I", "PT_WRITE_D", "PT_WRITE_U", "PT_CONTINUE", 264 "PT_KILL", "PT_STEP", "PT_ATTACH", "PT_DETACH", 265 }; 266 267 static void 268 ktrsyscall(struct ktr_syscall *ktr) 269 { 270 int narg = ktr->ktr_narg; 271 register_t *ip; 272 273 if (ktr->ktr_code >= nsyscalls || ktr->ktr_code < 0) 274 (void)printf("[%d]", ktr->ktr_code); 275 else 276 (void)printf("%s", syscallnames[ktr->ktr_code]); 277 ip = &ktr->ktr_args[0]; 278 if (narg) { 279 char c = '('; 280 if (fancy) { 281 282 #define print_number(i,n,c) do { \ 283 if (decimal) \ 284 (void)printf("%c%ld", c, (long)*i); \ 285 else \ 286 (void)printf("%c%#lx", c, (long)*i); \ 287 i++; \ 288 n--; \ 289 c = ','; \ 290 } while (0); 291 292 if (ktr->ktr_code == SYS_ioctl) { 293 const char *cp; 294 print_number(ip,narg,c); 295 if ((cp = ioctlname(*ip)) != NULL) 296 (void)printf(",%s", cp); 297 else { 298 if (decimal) 299 (void)printf(",%ld", (long)*ip); 300 else 301 (void)printf(",%#lx ", (long)*ip); 302 } 303 c = ','; 304 ip++; 305 narg--; 306 } else if (ktr->ktr_code == SYS_access) { 307 print_number(ip,narg,c); 308 (void)putchar(','); 309 accessmodename ((int)*ip); 310 ip++; 311 narg--; 312 } else if (ktr->ktr_code == SYS_open) { 313 int flags; 314 int mode; 315 print_number(ip,narg,c); 316 flags = *ip; 317 mode = *++ip; 318 (void)putchar(','); 319 flagsandmodename (flags, mode, decimal); 320 ip++; 321 narg-=2; 322 } else if (ktr->ktr_code == SYS_wait4) { 323 print_number(ip,narg,c); 324 print_number(ip,narg,c); 325 (void)putchar(','); 326 wait4optname ((int)*ip); 327 ip++; 328 narg--; 329 } else if (ktr->ktr_code == SYS_chmod || 330 ktr->ktr_code == SYS_fchmod || 331 ktr->ktr_code == SYS_lchmod) { 332 print_number(ip,narg,c); 333 (void)putchar(','); 334 modename ((int)*ip); 335 ip++; 336 narg--; 337 } else if (ktr->ktr_code == SYS_mknod) { 338 print_number(ip,narg,c); 339 (void)putchar(','); 340 modename ((int)*ip); 341 ip++; 342 narg--; 343 } else if (ktr->ktr_code == SYS_getfsstat) { 344 print_number(ip,narg,c); 345 print_number(ip,narg,c); 346 (void)putchar(','); 347 getfsstatflagsname ((int)*ip); 348 ip++; 349 narg--; 350 } else if (ktr->ktr_code == SYS_mount) { 351 print_number(ip,narg,c); 352 print_number(ip,narg,c); 353 (void)putchar(','); 354 mountflagsname ((int)*ip); 355 ip++; 356 narg--; 357 } else if (ktr->ktr_code == SYS_unmount) { 358 print_number(ip,narg,c); 359 (void)putchar(','); 360 mountflagsname ((int)*ip); 361 ip++; 362 narg--; 363 } else if (ktr->ktr_code == SYS_recvmsg || 364 ktr->ktr_code == SYS_sendmsg) { 365 print_number(ip,narg,c); 366 print_number(ip,narg,c); 367 (void)putchar(','); 368 sendrecvflagsname ((int)*ip); 369 ip++; 370 narg--; 371 } else if (ktr->ktr_code == SYS_recvfrom || 372 ktr->ktr_code == SYS_sendto) { 373 print_number(ip,narg,c); 374 print_number(ip,narg,c); 375 print_number(ip,narg,c); 376 (void)putchar(','); 377 sendrecvflagsname ((int)*ip); 378 ip++; 379 narg--; 380 } else if (ktr->ktr_code == SYS_chflags || 381 ktr->ktr_code == SYS_fchflags) { 382 print_number(ip,narg,c); 383 (void)putchar(','); 384 modename((int)*ip); 385 ip++; 386 narg--; 387 } else if (ktr->ktr_code == SYS_kill) { 388 print_number(ip,narg,c); 389 (void)putchar(','); 390 signame((int)*ip); 391 ip++; 392 narg--; 393 } else if (ktr->ktr_code == SYS_reboot) { 394 (void)putchar('('); 395 rebootoptname((int)*ip); 396 ip++; 397 narg--; 398 } else if (ktr->ktr_code == SYS_umask) { 399 (void)putchar('('); 400 modename((int)*ip); 401 ip++; 402 narg--; 403 } else if (ktr->ktr_code == SYS_msync) { 404 print_number(ip,narg,c); 405 print_number(ip,narg,c); 406 (void)putchar(','); 407 msyncflagsname((int)*ip); 408 ip++; 409 narg--; 410 } else if (ktr->ktr_code == SYS_mmap) { 411 print_number(ip,narg,c); 412 print_number(ip,narg,c); 413 (void)putchar(','); 414 mmapprotname ((int)*ip); 415 (void)putchar(','); 416 ip++; 417 narg--; 418 mmapflagsname ((int)*ip); 419 ip++; 420 narg--; 421 } else if (ktr->ktr_code == SYS_mprotect) { 422 print_number(ip,narg,c); 423 print_number(ip,narg,c); 424 (void)putchar(','); 425 mmapprotname ((int)*ip); 426 ip++; 427 narg--; 428 } else if (ktr->ktr_code == SYS_madvise) { 429 print_number(ip,narg,c); 430 print_number(ip,narg,c); 431 (void)putchar(','); 432 madvisebehavname((int)*ip); 433 ip++; 434 narg--; 435 } else if (ktr->ktr_code == SYS_setpriority) { 436 (void)putchar('('); 437 prioname((int)*ip); 438 ip++; 439 narg--; 440 c = ','; 441 print_number(ip,narg,c); 442 print_number(ip,narg,c); 443 } else if (ktr->ktr_code == SYS_fcntl) { 444 int cmd; 445 int arg; 446 print_number(ip,narg,c); 447 cmd = *ip; 448 arg = *++ip; 449 (void)putchar(','); 450 fcntlcmdname(cmd, arg, decimal); 451 ip++; 452 narg-=2; 453 } else if (ktr->ktr_code == SYS_socket) { 454 (void)putchar('('); 455 sockdomainname((int)*ip); 456 ip++; 457 narg--; 458 (void)putchar(','); 459 socktypename((int)*ip); 460 ip++; 461 narg--; 462 c = ','; 463 } else if (ktr->ktr_code == SYS_setsockopt || 464 ktr->ktr_code == SYS_getsockopt) { 465 print_number(ip,narg,c); 466 (void)putchar(','); 467 sockoptlevelname((int)*ip, decimal); 468 ip++; 469 narg--; 470 (void)putchar(','); 471 sockoptname((int)*ip); 472 ip++; 473 narg--; 474 } else if (ktr->ktr_code == SYS_lseek) { 475 print_number(ip,narg,c); 476 /* Hidden 'pad' argument, not in lseek(2) */ 477 print_number(ip,narg,c); 478 print_number(ip,narg,c); 479 (void)putchar(','); 480 whencename ((int)*ip); 481 ip++; 482 narg--; 483 } else if (ktr->ktr_code == SYS_flock) { 484 print_number(ip,narg,c); 485 (void)putchar(','); 486 flockname((int)*ip); 487 ip++; 488 narg--; 489 } else if (ktr->ktr_code == SYS_mkfifo || 490 ktr->ktr_code == SYS_mkdir) { 491 print_number(ip,narg,c); 492 (void)putchar(','); 493 modename((int)*ip); 494 ip++; 495 narg--; 496 } else if (ktr->ktr_code == SYS_shutdown) { 497 print_number(ip,narg,c); 498 (void)putchar(','); 499 shutdownhowname((int)*ip); 500 ip++; 501 narg--; 502 } else if (ktr->ktr_code == SYS_socketpair) { 503 (void)putchar('('); 504 sockdomainname((int)*ip); 505 ip++; 506 narg--; 507 (void)putchar(','); 508 socktypename((int)*ip); 509 ip++; 510 narg--; 511 c = ','; 512 } else if (ktr->ktr_code == SYS_getrlimit || 513 ktr->ktr_code == SYS_setrlimit) { 514 (void)putchar('('); 515 rlimitname((int)*ip); 516 ip++; 517 narg--; 518 c = ','; 519 } else if (ktr->ktr_code == SYS_quotactl) { 520 print_number(ip,narg,c); 521 quotactlname((int)*ip); 522 ip++; 523 narg--; 524 c = ','; 525 } else if (ktr->ktr_code == SYS_rtprio) { 526 (void)putchar('('); 527 rtprioname((int)*ip); 528 ip++; 529 narg--; 530 c = ','; 531 } else if (ktr->ktr_code == SYS___semctl) { 532 print_number(ip,narg,c); 533 print_number(ip,narg,c); 534 semctlname((int)*ip); 535 ip++; 536 narg--; 537 } else if (ktr->ktr_code == SYS_semget) { 538 print_number(ip,narg,c); 539 print_number(ip,narg,c); 540 semgetname((int)*ip); 541 ip++; 542 narg--; 543 } else if (ktr->ktr_code == SYS_msgctl) { 544 print_number(ip,narg,c); 545 shmctlname((int)*ip); 546 ip++; 547 narg--; 548 } else if (ktr->ktr_code == SYS_shmat) { 549 print_number(ip,narg,c); 550 print_number(ip,narg,c); 551 shmatname((int)*ip); 552 ip++; 553 narg--; 554 } else if (ktr->ktr_code == SYS_shmctl) { 555 print_number(ip,narg,c); 556 shmctlname((int)*ip); 557 ip++; 558 narg--; 559 } else if (ktr->ktr_code == SYS_minherit) { 560 print_number(ip,narg,c); 561 print_number(ip,narg,c); 562 minheritname((int)*ip); 563 ip++; 564 narg--; 565 } else if (ktr->ktr_code == SYS_rfork) { 566 (void)putchar('('); 567 rforkname((int)*ip); 568 ip++; 569 narg--; 570 c = ','; 571 } else if (ktr->ktr_code == SYS_lio_listio) { 572 (void)putchar('('); 573 lio_listioname((int)*ip); 574 ip++; 575 narg--; 576 c = ','; 577 } else if (ktr->ktr_code == SYS_mlockall) { 578 (void)putchar('('); 579 mlockallname((int)*ip); 580 ip++; 581 narg--; 582 } else if (ktr->ktr_code == SYS_sched_setscheduler) { 583 print_number(ip,narg,c); 584 schedpolicyname((int)*ip); 585 ip++; 586 narg--; 587 } else if (ktr->ktr_code == SYS_sched_get_priority_max || 588 ktr->ktr_code == SYS_sched_get_priority_min) { 589 (void)putchar('('); 590 schedpolicyname((int)*ip); 591 ip++; 592 narg--; 593 } else if (ktr->ktr_code == SYS_sendfile) { 594 print_number(ip,narg,c); 595 print_number(ip,narg,c); 596 print_number(ip,narg,c); 597 print_number(ip,narg,c); 598 print_number(ip,narg,c); 599 print_number(ip,narg,c); 600 sendfileflagsname((int)*ip); 601 ip++; 602 narg--; 603 } else if (ktr->ktr_code == SYS_kldsym) { 604 print_number(ip,narg,c); 605 kldsymcmdname((int)*ip); 606 ip++; 607 narg--; 608 } else if (ktr->ktr_code == SYS_sigprocmask) { 609 (void)putchar('('); 610 sigprocmaskhowname((int)*ip); 611 ip++; 612 narg--; 613 c = ','; 614 } else if (ktr->ktr_code == SYS___acl_get_file || 615 ktr->ktr_code == SYS___acl_set_file || 616 ktr->ktr_code == SYS___acl_get_fd || 617 ktr->ktr_code == SYS___acl_set_fd || 618 ktr->ktr_code == SYS___acl_delete_file || 619 ktr->ktr_code == SYS___acl_delete_fd || 620 ktr->ktr_code == SYS___acl_aclcheck_file || 621 ktr->ktr_code == SYS___acl_aclcheck_fd) { 622 print_number(ip,narg,c); 623 acltypename((int)*ip); 624 ip++; 625 narg--; 626 } else if (ktr->ktr_code == SYS_sigaction) { 627 (void)putchar('('); 628 signame((int)*ip); 629 ip++; 630 narg--; 631 c = ','; 632 } else if (ktr->ktr_code == SYS_extattrctl) { 633 print_number(ip,narg,c); 634 extattrctlname((int)*ip); 635 ip++; 636 narg--; 637 } else if (ktr->ktr_code == SYS_ptrace) { 638 if (*ip < (register_t)(sizeof(ptrace_ops) / 639 sizeof(ptrace_ops[0])) && *ip >= 0) 640 (void)printf("(%s", ptrace_ops[*ip]); 641 #ifdef PT_GETREGS 642 else if (*ip == PT_GETREGS) 643 (void)printf("(%s", "PT_GETREGS"); 644 #endif 645 #ifdef PT_SETREGS 646 else if (*ip == PT_SETREGS) 647 (void)printf("(%s", "PT_SETREGS"); 648 #endif 649 #ifdef PT_GETFPREGS 650 else if (*ip == PT_GETFPREGS) 651 (void)printf("(%s", "PT_GETFPREGS"); 652 #endif 653 #ifdef PT_SETFPREGS 654 else if (*ip == PT_SETFPREGS) 655 (void)printf("(%s", "PT_SETFPREGS"); 656 #endif 657 #ifdef PT_GETDBREGS 658 else if (*ip == PT_GETDBREGS) 659 (void)printf("(%s", "PT_GETDBREGS"); 660 #endif 661 #ifdef PT_SETDBREGS 662 else if (*ip == PT_SETDBREGS) 663 (void)printf("(%s", "PT_SETDBREGS"); 664 #endif 665 else 666 (void)printf("(%ld", (long)*ip); 667 c = ','; 668 ip++; 669 narg--; 670 } 671 } 672 while (narg > 0) { 673 print_number(ip,narg,c); 674 } 675 (void)putchar(')'); 676 } 677 (void)putchar('\n'); 678 } 679 680 static void 681 ktrsysret(struct ktr_sysret *ktr) 682 { 683 register_t ret = ktr->ktr_retval; 684 int error = ktr->ktr_error; 685 int code = ktr->ktr_code; 686 687 if (code >= nsyscalls || code < 0) 688 (void)printf("[%d] ", code); 689 else 690 (void)printf("%s ", syscallnames[code]); 691 692 if (error == 0) { 693 if (fancy) { 694 (void)printf("%ld", (long)ret); 695 if (ret < 0 || ret > 9) 696 (void)printf("/%#lx", (long)ret); 697 } else { 698 if (decimal) 699 (void)printf("%ld", (long)ret); 700 else 701 (void)printf("%#lx", (long)ret); 702 } 703 } else if (error == ERESTART) 704 (void)printf("RESTART"); 705 else if (error == EJUSTRETURN) 706 (void)printf("JUSTRETURN"); 707 else { 708 (void)printf("-1 errno %d", ktr->ktr_error); 709 if (fancy) 710 (void)printf(" %s", strerror(ktr->ktr_error)); 711 } 712 (void)putchar('\n'); 713 } 714 715 static void 716 ktrnamei(char *cp, int len) 717 { 718 (void)printf("\"%.*s\"\n", len, cp); 719 } 720 721 static void 722 ktrgenio(struct ktr_genio *ktr, int len) 723 { 724 int datalen = len - sizeof (struct ktr_genio); 725 char *dp = (char *)ktr + sizeof (struct ktr_genio); 726 char *cp; 727 int col = 0; 728 int width; 729 char visbuf[5]; 730 static int screenwidth = 0; 731 732 if (screenwidth == 0) { 733 struct winsize ws; 734 735 if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 && 736 ws.ws_col > 8) 737 screenwidth = ws.ws_col; 738 else 739 screenwidth = 80; 740 } 741 printf("fd %d %s %d byte%s\n", ktr->ktr_fd, 742 ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen, 743 datalen == 1 ? "" : "s"); 744 if (maxdata && datalen > maxdata) 745 datalen = maxdata; 746 (void)printf(" \""); 747 col = 8; 748 for (;datalen > 0; datalen--, dp++) { 749 (void) vis(visbuf, *dp, VIS_CSTYLE, *(dp+1)); 750 cp = visbuf; 751 /* 752 * Keep track of printables and 753 * space chars (like fold(1)). 754 */ 755 if (col == 0) { 756 (void)putchar('\t'); 757 col = 8; 758 } 759 switch(*cp) { 760 case '\n': 761 col = 0; 762 (void)putchar('\n'); 763 continue; 764 case '\t': 765 width = 8 - (col&07); 766 break; 767 default: 768 width = strlen(cp); 769 } 770 if (col + width > (screenwidth-2)) { 771 (void)printf("\\\n\t"); 772 col = 8; 773 } 774 col += width; 775 do { 776 (void)putchar(*cp++); 777 } while (*cp); 778 } 779 if (col == 0) 780 (void)printf(" "); 781 (void)printf("\"\n"); 782 } 783 784 const char *signames[NSIG] = { 785 "NULL", "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT", /* 1 - 6 */ 786 "EMT", "FPE", "KILL", "BUS", "SEGV", "SYS", /* 7 - 12 */ 787 "PIPE", "ALRM", "TERM", "URG", "STOP", "TSTP", /* 13 - 18 */ 788 "CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU", /* 19 - 24 */ 789 "XFSZ", "VTALRM", "PROF", "WINCH", "29", "USR1", /* 25 - 30 */ 790 "USR2", NULL, /* 31 - 32 */ 791 }; 792 793 static void 794 ktrpsig(struct ktr_psig *psig) 795 { 796 (void)printf("SIG%s ", signames[psig->signo]); 797 if (psig->action == SIG_DFL) 798 (void)printf("SIG_DFL\n"); 799 else 800 (void)printf("caught handler=0x%lx mask=0x%x code=0x%x\n", 801 (u_long)psig->action, psig->mask.__bits[0], psig->code); 802 } 803 804 static void 805 ktrcsw(struct ktr_csw *cs) 806 { 807 (void)printf("%s %s\n", cs->out ? "stop" : "resume", 808 cs->user ? "user" : "kernel"); 809 } 810 811 struct utrace_malloc { 812 void *p; 813 size_t s; 814 void *r; 815 }; 816 817 static void 818 ktruser_malloc(int len __unused, unsigned char *p) 819 { 820 struct utrace_malloc *ut = (struct utrace_malloc *)p; 821 822 if (ut->p == NULL) { 823 if (ut->s == 0 && ut->r == NULL) 824 printf("malloc_init()\n"); 825 else 826 printf("%p = malloc(%zu)\n", ut->r, ut->s); 827 } else { 828 if (ut->s == 0) 829 printf("free(%p)\n", ut->p); 830 else 831 printf("%p = realloc(%p, %zu)\n", ut->r, ut->p, ut->s); 832 } 833 } 834 835 static void 836 ktruser(int len, unsigned char *p) 837 { 838 if (len == sizeof(struct utrace_malloc)) { 839 ktruser_malloc(len, p); 840 return; 841 } 842 843 (void)printf("%d ", len); 844 while (len--) 845 (void)printf(" %02x", *p++); 846 (void)printf("\n"); 847 } 848 849 static void 850 usage(void) 851 { 852 (void)fprintf(stderr, 853 "usage: kdump [-dnlRT] [-f trfile] [-m maxdata] [-t [cnisuw]] [-p pid]\n"); 854 exit(1); 855 } 856 857 static void 858 timevalsub(struct timeval *t1, struct timeval *t2) 859 { 860 t1->tv_sec -= t2->tv_sec; 861 t1->tv_usec -= t2->tv_usec; 862 timevalfix(t1); 863 } 864 865 static void 866 timevalfix(struct timeval *t1) 867 { 868 if (t1->tv_usec < 0) { 869 t1->tv_sec--; 870 t1->tv_usec += 1000000; 871 } 872 if (t1->tv_usec >= 1000000) { 873 t1->tv_sec++; 874 t1->tv_usec -= 1000000; 875 } 876 } 877