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 */ 37 38 #define _KERNEL_STRUCTURES 39 40 #include <sys/errno.h> 41 #include <sys/param.h> 42 #include <sys/time.h> 43 #include <sys/uio.h> 44 #include <sys/ktrace.h> 45 #include <sys/ioctl.h> 46 #include <sys/ptrace.h> 47 #include <dlfcn.h> 48 #include <err.h> 49 #include <locale.h> 50 #include <stdio.h> 51 #include <stdlib.h> 52 #include <string.h> 53 #include <unistd.h> 54 #include <vis.h> 55 #include "ktrace.h" 56 #include "kdump_subr.h" 57 58 extern const char *ioctlname(u_long); 59 60 static int dumpheader(struct ktr_header *); 61 static int fread_tail(void *, int, int); 62 static void ktrcsw(struct ktr_csw *); 63 static void ktrgenio(struct ktr_genio *, int); 64 static void ktrnamei(char *, int); 65 static void ktrpsig(struct ktr_psig *); 66 static void ktrsyscall(struct ktr_syscall *); 67 static void ktrsysret(struct ktr_sysret *); 68 static void ktruser(int, unsigned char *); 69 static void ktruser_malloc(int, unsigned char *); 70 static void ktruser_rtld(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 ktr->ktr_code == SYS_mq_open) { 314 int flags; 315 int mode; 316 print_number(ip,narg,c); 317 flags = *ip; 318 mode = *++ip; 319 (void)putchar(','); 320 flagsandmodename (flags, mode, decimal); 321 ip++; 322 narg-=2; 323 } else if (ktr->ktr_code == SYS_wait4) { 324 print_number(ip,narg,c); 325 print_number(ip,narg,c); 326 (void)putchar(','); 327 wait4optname ((int)*ip); 328 ip++; 329 narg--; 330 } else if (ktr->ktr_code == SYS_chmod || 331 ktr->ktr_code == SYS_fchmod || 332 ktr->ktr_code == SYS_lchmod) { 333 print_number(ip,narg,c); 334 (void)putchar(','); 335 modename ((int)*ip); 336 ip++; 337 narg--; 338 } else if (ktr->ktr_code == SYS_mknod) { 339 print_number(ip,narg,c); 340 (void)putchar(','); 341 modename ((int)*ip); 342 ip++; 343 narg--; 344 } else if (ktr->ktr_code == SYS_getfsstat) { 345 print_number(ip,narg,c); 346 print_number(ip,narg,c); 347 (void)putchar(','); 348 getfsstatflagsname ((int)*ip); 349 ip++; 350 narg--; 351 } else if (ktr->ktr_code == SYS_mount) { 352 print_number(ip,narg,c); 353 print_number(ip,narg,c); 354 (void)putchar(','); 355 mountflagsname ((int)*ip); 356 ip++; 357 narg--; 358 } else if (ktr->ktr_code == SYS_unmount) { 359 print_number(ip,narg,c); 360 (void)putchar(','); 361 mountflagsname ((int)*ip); 362 ip++; 363 narg--; 364 } else if (ktr->ktr_code == SYS_recvmsg || 365 ktr->ktr_code == SYS_sendmsg) { 366 print_number(ip,narg,c); 367 print_number(ip,narg,c); 368 (void)putchar(','); 369 sendrecvflagsname ((int)*ip); 370 ip++; 371 narg--; 372 } else if (ktr->ktr_code == SYS_recvfrom || 373 ktr->ktr_code == SYS_sendto) { 374 print_number(ip,narg,c); 375 print_number(ip,narg,c); 376 print_number(ip,narg,c); 377 (void)putchar(','); 378 sendrecvflagsname ((int)*ip); 379 ip++; 380 narg--; 381 } else if (ktr->ktr_code == SYS_chflags || 382 ktr->ktr_code == SYS_fchflags) { 383 print_number(ip,narg,c); 384 (void)putchar(','); 385 modename((int)*ip); 386 ip++; 387 narg--; 388 } else if (ktr->ktr_code == SYS_kill) { 389 print_number(ip,narg,c); 390 (void)putchar(','); 391 signame((int)*ip); 392 ip++; 393 narg--; 394 } else if (ktr->ktr_code == SYS_reboot) { 395 (void)putchar('('); 396 rebootoptname((int)*ip); 397 ip++; 398 narg--; 399 } else if (ktr->ktr_code == SYS_umask) { 400 (void)putchar('('); 401 modename((int)*ip); 402 ip++; 403 narg--; 404 } else if (ktr->ktr_code == SYS_msync) { 405 print_number(ip,narg,c); 406 print_number(ip,narg,c); 407 (void)putchar(','); 408 msyncflagsname((int)*ip); 409 ip++; 410 narg--; 411 } else if (ktr->ktr_code == SYS_mmap) { 412 print_number(ip,narg,c); 413 print_number(ip,narg,c); 414 (void)putchar(','); 415 mmapprotname ((int)*ip); 416 (void)putchar(','); 417 ip++; 418 narg--; 419 mmapflagsname ((int)*ip); 420 ip++; 421 narg--; 422 } else if (ktr->ktr_code == SYS_mprotect) { 423 print_number(ip,narg,c); 424 print_number(ip,narg,c); 425 (void)putchar(','); 426 mmapprotname ((int)*ip); 427 ip++; 428 narg--; 429 } else if (ktr->ktr_code == SYS_madvise) { 430 print_number(ip,narg,c); 431 print_number(ip,narg,c); 432 (void)putchar(','); 433 madvisebehavname((int)*ip); 434 ip++; 435 narg--; 436 } else if (ktr->ktr_code == SYS_setpriority) { 437 (void)putchar('('); 438 prioname((int)*ip); 439 ip++; 440 narg--; 441 c = ','; 442 print_number(ip,narg,c); 443 print_number(ip,narg,c); 444 } else if (ktr->ktr_code == SYS_fcntl) { 445 int cmd; 446 int arg; 447 print_number(ip,narg,c); 448 cmd = *ip; 449 arg = *++ip; 450 (void)putchar(','); 451 fcntlcmdname(cmd, arg, decimal); 452 ip++; 453 narg-=2; 454 } else if (ktr->ktr_code == SYS_socket) { 455 (void)putchar('('); 456 sockdomainname((int)*ip); 457 ip++; 458 narg--; 459 (void)putchar(','); 460 socktypename((int)*ip); 461 ip++; 462 narg--; 463 c = ','; 464 } else if (ktr->ktr_code == SYS_setsockopt || 465 ktr->ktr_code == SYS_getsockopt) { 466 print_number(ip,narg,c); 467 (void)putchar(','); 468 sockoptlevelname((int)*ip, decimal); 469 ip++; 470 narg--; 471 (void)putchar(','); 472 sockoptname((int)*ip); 473 ip++; 474 narg--; 475 } else if (ktr->ktr_code == SYS_lseek) { 476 print_number(ip,narg,c); 477 /* Hidden 'pad' argument, not in lseek(2) */ 478 print_number(ip,narg,c); 479 print_number(ip,narg,c); 480 (void)putchar(','); 481 whencename ((int)*ip); 482 ip++; 483 narg--; 484 } else if (ktr->ktr_code == SYS_flock) { 485 print_number(ip,narg,c); 486 (void)putchar(','); 487 flockname((int)*ip); 488 ip++; 489 narg--; 490 } else if (ktr->ktr_code == SYS_mkfifo || 491 ktr->ktr_code == SYS_mkdir) { 492 print_number(ip,narg,c); 493 (void)putchar(','); 494 modename((int)*ip); 495 ip++; 496 narg--; 497 } else if (ktr->ktr_code == SYS_shutdown) { 498 print_number(ip,narg,c); 499 (void)putchar(','); 500 shutdownhowname((int)*ip); 501 ip++; 502 narg--; 503 } else if (ktr->ktr_code == SYS_socketpair) { 504 (void)putchar('('); 505 sockdomainname((int)*ip); 506 ip++; 507 narg--; 508 (void)putchar(','); 509 socktypename((int)*ip); 510 ip++; 511 narg--; 512 c = ','; 513 } else if (ktr->ktr_code == SYS_getrlimit || 514 ktr->ktr_code == SYS_setrlimit) { 515 (void)putchar('('); 516 rlimitname((int)*ip); 517 ip++; 518 narg--; 519 c = ','; 520 } else if (ktr->ktr_code == SYS_quotactl) { 521 print_number(ip,narg,c); 522 quotactlname((int)*ip); 523 ip++; 524 narg--; 525 c = ','; 526 } else if (ktr->ktr_code == SYS_rtprio) { 527 (void)putchar('('); 528 rtprioname((int)*ip); 529 ip++; 530 narg--; 531 c = ','; 532 } else if (ktr->ktr_code == SYS___semctl) { 533 print_number(ip,narg,c); 534 print_number(ip,narg,c); 535 semctlname((int)*ip); 536 ip++; 537 narg--; 538 } else if (ktr->ktr_code == SYS_semget) { 539 print_number(ip,narg,c); 540 print_number(ip,narg,c); 541 semgetname((int)*ip); 542 ip++; 543 narg--; 544 } else if (ktr->ktr_code == SYS_msgctl) { 545 print_number(ip,narg,c); 546 shmctlname((int)*ip); 547 ip++; 548 narg--; 549 } else if (ktr->ktr_code == SYS_shmat) { 550 print_number(ip,narg,c); 551 print_number(ip,narg,c); 552 shmatname((int)*ip); 553 ip++; 554 narg--; 555 } else if (ktr->ktr_code == SYS_shmctl) { 556 print_number(ip,narg,c); 557 shmctlname((int)*ip); 558 ip++; 559 narg--; 560 } else if (ktr->ktr_code == SYS_minherit) { 561 print_number(ip,narg,c); 562 print_number(ip,narg,c); 563 minheritname((int)*ip); 564 ip++; 565 narg--; 566 } else if (ktr->ktr_code == SYS_rfork) { 567 (void)putchar('('); 568 rforkname((int)*ip); 569 ip++; 570 narg--; 571 c = ','; 572 } else if (ktr->ktr_code == SYS_lio_listio) { 573 (void)putchar('('); 574 lio_listioname((int)*ip); 575 ip++; 576 narg--; 577 c = ','; 578 } else if (ktr->ktr_code == SYS_mlockall) { 579 (void)putchar('('); 580 mlockallname((int)*ip); 581 ip++; 582 narg--; 583 } else if (ktr->ktr_code == SYS_sched_setscheduler) { 584 print_number(ip,narg,c); 585 schedpolicyname((int)*ip); 586 ip++; 587 narg--; 588 } else if (ktr->ktr_code == SYS_sched_get_priority_max || 589 ktr->ktr_code == SYS_sched_get_priority_min) { 590 (void)putchar('('); 591 schedpolicyname((int)*ip); 592 ip++; 593 narg--; 594 } else if (ktr->ktr_code == SYS_sendfile) { 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 print_number(ip,narg,c); 601 sendfileflagsname((int)*ip); 602 ip++; 603 narg--; 604 } else if (ktr->ktr_code == SYS_kldsym) { 605 print_number(ip,narg,c); 606 kldsymcmdname((int)*ip); 607 ip++; 608 narg--; 609 } else if (ktr->ktr_code == SYS_sigprocmask) { 610 (void)putchar('('); 611 sigprocmaskhowname((int)*ip); 612 ip++; 613 narg--; 614 c = ','; 615 } else if (ktr->ktr_code == SYS___acl_get_file || 616 ktr->ktr_code == SYS___acl_set_file || 617 ktr->ktr_code == SYS___acl_get_fd || 618 ktr->ktr_code == SYS___acl_set_fd || 619 ktr->ktr_code == SYS___acl_delete_file || 620 ktr->ktr_code == SYS___acl_delete_fd || 621 ktr->ktr_code == SYS___acl_aclcheck_file || 622 ktr->ktr_code == SYS___acl_aclcheck_fd) { 623 print_number(ip,narg,c); 624 acltypename((int)*ip); 625 ip++; 626 narg--; 627 } else if (ktr->ktr_code == SYS_sigaction) { 628 (void)putchar('('); 629 signame((int)*ip); 630 ip++; 631 narg--; 632 c = ','; 633 } else if (ktr->ktr_code == SYS_extattrctl) { 634 print_number(ip,narg,c); 635 extattrctlname((int)*ip); 636 ip++; 637 narg--; 638 } else if (ktr->ktr_code == SYS_ptrace) { 639 if (*ip < (register_t)(sizeof(ptrace_ops) / 640 sizeof(ptrace_ops[0])) && *ip >= 0) 641 (void)printf("(%s", ptrace_ops[*ip]); 642 #ifdef PT_GETREGS 643 else if (*ip == PT_GETREGS) 644 (void)printf("(%s", "PT_GETREGS"); 645 #endif 646 #ifdef PT_SETREGS 647 else if (*ip == PT_SETREGS) 648 (void)printf("(%s", "PT_SETREGS"); 649 #endif 650 #ifdef PT_GETFPREGS 651 else if (*ip == PT_GETFPREGS) 652 (void)printf("(%s", "PT_GETFPREGS"); 653 #endif 654 #ifdef PT_SETFPREGS 655 else if (*ip == PT_SETFPREGS) 656 (void)printf("(%s", "PT_SETFPREGS"); 657 #endif 658 #ifdef PT_GETDBREGS 659 else if (*ip == PT_GETDBREGS) 660 (void)printf("(%s", "PT_GETDBREGS"); 661 #endif 662 #ifdef PT_SETDBREGS 663 else if (*ip == PT_SETDBREGS) 664 (void)printf("(%s", "PT_SETDBREGS"); 665 #endif 666 else 667 (void)printf("(%ld", (long)*ip); 668 c = ','; 669 ip++; 670 narg--; 671 } 672 } 673 while (narg > 0) { 674 print_number(ip,narg,c); 675 } 676 (void)putchar(')'); 677 } 678 (void)putchar('\n'); 679 } 680 681 static void 682 ktrsysret(struct ktr_sysret *ktr) 683 { 684 register_t ret = ktr->ktr_retval; 685 int error = ktr->ktr_error; 686 int code = ktr->ktr_code; 687 688 if (code >= nsyscalls || code < 0) 689 (void)printf("[%d] ", code); 690 else 691 (void)printf("%s ", syscallnames[code]); 692 693 if (error == 0) { 694 if (fancy) { 695 (void)printf("%ld", (long)ret); 696 if (ret < 0 || ret > 9) 697 (void)printf("/%#lx", (long)ret); 698 } else { 699 if (decimal) 700 (void)printf("%ld", (long)ret); 701 else 702 (void)printf("%#lx", (long)ret); 703 } 704 } else if (error == ERESTART) 705 (void)printf("RESTART"); 706 else if (error == EJUSTRETURN) 707 (void)printf("JUSTRETURN"); 708 else { 709 (void)printf("-1 errno %d", ktr->ktr_error); 710 if (fancy) 711 (void)printf(" %s", strerror(ktr->ktr_error)); 712 } 713 (void)putchar('\n'); 714 } 715 716 static void 717 ktrnamei(char *cp, int len) 718 { 719 (void)printf("\"%.*s\"\n", len, cp); 720 } 721 722 static void 723 ktrgenio(struct ktr_genio *ktr, int len) 724 { 725 int datalen = len - sizeof (struct ktr_genio); 726 char *dp = (char *)ktr + sizeof (struct ktr_genio); 727 char *cp; 728 int col = 0; 729 int width; 730 char visbuf[5]; 731 static int screenwidth = 0; 732 733 if (screenwidth == 0) { 734 struct winsize ws; 735 736 if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 && 737 ws.ws_col > 8) 738 screenwidth = ws.ws_col; 739 else 740 screenwidth = 80; 741 } 742 printf("fd %d %s %d byte%s\n", ktr->ktr_fd, 743 ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen, 744 datalen == 1 ? "" : "s"); 745 if (maxdata && datalen > maxdata) 746 datalen = maxdata; 747 (void)printf(" \""); 748 col = 8; 749 for (;datalen > 0; datalen--, dp++) { 750 (void) vis(visbuf, *dp, VIS_CSTYLE, *(dp+1)); 751 cp = visbuf; 752 /* 753 * Keep track of printables and 754 * space chars (like fold(1)). 755 */ 756 if (col == 0) { 757 (void)putchar('\t'); 758 col = 8; 759 } 760 switch(*cp) { 761 case '\n': 762 col = 0; 763 (void)putchar('\n'); 764 continue; 765 case '\t': 766 width = 8 - (col&07); 767 break; 768 default: 769 width = strlen(cp); 770 } 771 if (col + width > (screenwidth-2)) { 772 (void)printf("\\\n\t"); 773 col = 8; 774 } 775 col += width; 776 do { 777 (void)putchar(*cp++); 778 } while (*cp); 779 } 780 if (col == 0) 781 (void)printf(" "); 782 (void)printf("\"\n"); 783 } 784 785 const char *signames[NSIG] = { 786 "NULL", "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT", /* 1 - 6 */ 787 "EMT", "FPE", "KILL", "BUS", "SEGV", "SYS", /* 7 - 12 */ 788 "PIPE", "ALRM", "TERM", "URG", "STOP", "TSTP", /* 13 - 18 */ 789 "CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU", /* 19 - 24 */ 790 "XFSZ", "VTALRM", "PROF", "WINCH", "29", "USR1", /* 25 - 30 */ 791 "USR2", NULL, /* 31 - 32 */ 792 }; 793 794 static void 795 ktrpsig(struct ktr_psig *psig) 796 { 797 (void)printf("SIG%s ", signames[psig->signo]); 798 if (psig->action == SIG_DFL) 799 (void)printf("SIG_DFL\n"); 800 else 801 (void)printf("caught handler=0x%lx mask=0x%x code=0x%x\n", 802 (u_long)psig->action, psig->mask.__bits[0], psig->code); 803 } 804 805 static void 806 ktrcsw(struct ktr_csw *cs) 807 { 808 (void)printf("%s %s\n", cs->out ? "stop" : "resume", 809 cs->user ? "user" : "kernel"); 810 } 811 812 #define UTRACE_DLOPEN_START 1 813 #define UTRACE_DLOPEN_STOP 2 814 #define UTRACE_DLCLOSE_START 3 815 #define UTRACE_DLCLOSE_STOP 4 816 #define UTRACE_LOAD_OBJECT 5 817 #define UTRACE_UNLOAD_OBJECT 6 818 #define UTRACE_ADD_RUNDEP 7 819 #define UTRACE_PRELOAD_FINISHED 8 820 #define UTRACE_INIT_CALL 9 821 #define UTRACE_FINI_CALL 10 822 823 struct utrace_rtld { 824 char sig[4]; /* 'RTLD' */ 825 int event; 826 void *handle; 827 void *mapbase; 828 size_t mapsize; 829 int refcnt; 830 char name[MAXPATHLEN]; 831 }; 832 833 static void 834 ktruser_rtld(int len, unsigned char *p) 835 { 836 struct utrace_rtld *ut = (struct utrace_rtld *)p; 837 void *parent; 838 int mode; 839 840 switch (ut->event) { 841 case UTRACE_DLOPEN_START: 842 mode = ut->refcnt; 843 printf("dlopen(%s, ", ut->name); 844 switch (mode & RTLD_MODEMASK) { 845 case RTLD_NOW: 846 printf("RTLD_NOW"); 847 break; 848 case RTLD_LAZY: 849 printf("RTLD_LAZY"); 850 break; 851 default: 852 printf("%#x", mode & RTLD_MODEMASK); 853 } 854 if (mode & RTLD_GLOBAL) 855 printf(" | RTLD_GLOBAL"); 856 if (mode & RTLD_TRACE) 857 printf(" | RTLD_TRACE"); 858 if (mode & ~(RTLD_MODEMASK | RTLD_GLOBAL | RTLD_TRACE)) 859 printf(" | %#x", mode & 860 ~(RTLD_MODEMASK | RTLD_GLOBAL | RTLD_TRACE)); 861 printf(")\n"); 862 break; 863 case UTRACE_DLOPEN_STOP: 864 printf("%p = dlopen(%s) ref %d\n", ut->handle, ut->name, 865 ut->refcnt); 866 break; 867 case UTRACE_DLCLOSE_START: 868 printf("dlclose(%p) (%s, %d)\n", ut->handle, ut->name, 869 ut->refcnt); 870 break; 871 case UTRACE_DLCLOSE_STOP: 872 printf("dlclose(%p) finished\n", ut->handle); 873 break; 874 case UTRACE_LOAD_OBJECT: 875 printf("RTLD: loaded %p @ %p - %p (%s)\n", ut->handle, 876 ut->mapbase, (char *)ut->mapbase + ut->mapsize - 1, 877 ut->name); 878 break; 879 case UTRACE_UNLOAD_OBJECT: 880 printf("RTLD: unloaded %p @ %p - %p (%s)\n", ut->handle, 881 ut->mapbase, (char *)ut->mapbase + ut->mapsize - 1, 882 ut->name); 883 break; 884 case UTRACE_ADD_RUNDEP: 885 parent = ut->mapbase; 886 printf("RTLD: %p now depends on %p (%s, %d)\n", parent, 887 ut->handle, ut->name, ut->refcnt); 888 break; 889 case UTRACE_PRELOAD_FINISHED: 890 printf("RTLD: LD_PRELOAD finished\n"); 891 break; 892 case UTRACE_INIT_CALL: 893 printf("RTLD: init %p for %p (%s)\n", ut->mapbase, ut->handle, 894 ut->name); 895 break; 896 case UTRACE_FINI_CALL: 897 printf("RTLD: fini %p for %p (%s)\n", ut->mapbase, ut->handle, 898 ut->name); 899 break; 900 default: 901 p += 4; 902 len -= 4; 903 printf("RTLD: %d ", len); 904 while (len--) 905 if (decimal) 906 printf(" %d", *p++); 907 else 908 printf(" %02x", *p++); 909 printf("\n"); 910 } 911 } 912 913 struct utrace_malloc { 914 void *p; 915 size_t s; 916 void *r; 917 }; 918 919 static void 920 ktruser_malloc(int len __unused, unsigned char *p) 921 { 922 struct utrace_malloc *ut = (struct utrace_malloc *)p; 923 924 if (ut->p == NULL) { 925 if (ut->s == 0 && ut->r == NULL) 926 printf("malloc_init()\n"); 927 else 928 printf("%p = malloc(%zu)\n", ut->r, ut->s); 929 } else { 930 if (ut->s == 0) 931 printf("free(%p)\n", ut->p); 932 else 933 printf("%p = realloc(%p, %zu)\n", ut->r, ut->p, ut->s); 934 } 935 } 936 937 static void 938 ktruser(int len, unsigned char *p) 939 { 940 941 if (len >= 8 && bcmp(p, "RTLD", 4) == 0) { 942 ktruser_rtld(len, p); 943 return; 944 } 945 946 if (len == sizeof(struct utrace_malloc)) { 947 ktruser_malloc(len, p); 948 return; 949 } 950 951 (void)printf("%d ", len); 952 while (len--) 953 (void)printf(" %02x", *p++); 954 (void)printf("\n"); 955 } 956 957 static void 958 usage(void) 959 { 960 (void)fprintf(stderr, 961 "usage: kdump [-dnlRT] [-f trfile] [-m maxdata] [-t [cnisuw]] [-p pid]\n"); 962 exit(1); 963 } 964 965 static void 966 timevalsub(struct timeval *t1, struct timeval *t2) 967 { 968 t1->tv_sec -= t2->tv_sec; 969 t1->tv_usec -= t2->tv_usec; 970 timevalfix(t1); 971 } 972 973 static void 974 timevalfix(struct timeval *t1) 975 { 976 if (t1->tv_usec < 0) { 977 t1->tv_sec--; 978 t1->tv_usec += 1000000; 979 } 980 if (t1->tv_usec >= 1000000) { 981 t1->tv_sec++; 982 t1->tv_usec -= 1000000; 983 } 984 } 985