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/errno.h> 43 #include <sys/time.h> 44 #include <sys/uio.h> 45 #include <sys/ktrace.h> 46 #include <sys/ioctl.h> 47 #include <sys/ptrace.h> 48 #include <dlfcn.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 ktruser_rtld(int, unsigned char *); 72 static void timevalfix(struct timeval *); 73 static void timevalsub(struct timeval *, struct timeval *); 74 static void usage(void); 75 76 int timestamp, decimal, fancy = 1, tail, maxdata = 64; 77 int fixedformat; 78 const char *tracefile = DEF_TRACEFILE; 79 struct ktr_header ktr_header; 80 81 #define eqs(s1, s2) (strcmp((s1), (s2)) == 0) 82 83 int 84 main(int argc, char **argv) 85 { 86 int ch, col, ktrlen, size; 87 pid_t do_pid = -1; 88 void *m; 89 int trpoints = ALL_POINTS; 90 char *cp; 91 92 (void) setlocale(LC_CTYPE, ""); 93 94 while ((ch = getopt(argc,argv,"f:djlm:np:RTt:")) != -1) 95 switch((char)ch) { 96 case 'f': 97 tracefile = optarg; 98 break; 99 case 'j': 100 fixedformat = 1; 101 break; 102 case 'd': 103 decimal = 1; 104 break; 105 case 'l': 106 tail = 1; 107 break; 108 case 'm': 109 maxdata = atoi(optarg); 110 break; 111 case 'n': 112 fancy = 0; 113 break; 114 case 'p': 115 do_pid = strtoul(optarg, &cp, 0); 116 if (*cp != 0) 117 errx(1,"invalid number %s", optarg); 118 break; 119 case 'R': 120 timestamp = 2; /* relative timestamp */ 121 break; 122 case 'T': 123 timestamp = 1; 124 break; 125 case 't': 126 trpoints = getpoints(optarg); 127 if (trpoints < 0) 128 errx(1, "unknown trace point in %s", optarg); 129 break; 130 default: 131 usage(); 132 } 133 134 if (argc > optind) 135 usage(); 136 137 m = (void *)malloc(size = 1025); 138 if (m == NULL) 139 errx(1, "%s", strerror(ENOMEM)); 140 if (!freopen(tracefile, "r", stdin)) 141 err(1, "%s", tracefile); 142 while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) { 143 if (trpoints & (1 << ktr_header.ktr_type) && 144 (do_pid == -1 || ktr_header.ktr_pid == do_pid)) 145 col = dumpheader(&ktr_header); 146 else 147 col = -1; 148 if ((ktrlen = ktr_header.ktr_len) < 0) 149 errx(1, "bogus length 0x%x", ktrlen); 150 if (ktrlen > size) { 151 m = (void *)realloc(m, ktrlen+1); 152 if (m == NULL) 153 errx(1, "%s", strerror(ENOMEM)); 154 size = ktrlen; 155 } 156 if (ktrlen && fread_tail(m, ktrlen, 1) == 0) 157 errx(1, "data too short"); 158 if ((trpoints & (1<<ktr_header.ktr_type)) == 0) 159 continue; 160 if (col == -1) 161 continue; 162 switch (ktr_header.ktr_type) { 163 case KTR_SYSCALL: 164 ktrsyscall((struct ktr_syscall *)m); 165 break; 166 case KTR_SYSRET: 167 ktrsysret((struct ktr_sysret *)m); 168 break; 169 case KTR_NAMEI: 170 ktrnamei(m, ktrlen); 171 break; 172 case KTR_GENIO: 173 ktrgenio((struct ktr_genio *)m, ktrlen); 174 break; 175 case KTR_PSIG: 176 ktrpsig((struct ktr_psig *)m); 177 break; 178 case KTR_CSW: 179 ktrcsw((struct ktr_csw *)m); 180 break; 181 case KTR_USER: 182 ktruser(ktrlen, m); 183 break; 184 } 185 if (tail) 186 (void)fflush(stdout); 187 } 188 exit(0); 189 } 190 191 static int 192 fread_tail(void *buf, int size, int num) 193 { 194 int i; 195 196 while ((i = fread(buf, size, num, stdin)) == 0 && tail) { 197 (void)sleep(1); 198 clearerr(stdin); 199 } 200 return (i); 201 } 202 203 static int 204 dumpheader(struct ktr_header *kth) 205 { 206 static char unknown[64]; 207 static struct timeval prevtime, temp; 208 const char *type; 209 int col; 210 211 switch (kth->ktr_type) { 212 case KTR_SYSCALL: 213 type = "CALL"; 214 break; 215 case KTR_SYSRET: 216 type = "RET "; 217 break; 218 case KTR_NAMEI: 219 type = "NAMI"; 220 break; 221 case KTR_GENIO: 222 type = "GIO "; 223 break; 224 case KTR_PSIG: 225 type = "PSIG"; 226 break; 227 case KTR_CSW: 228 type = "CSW"; 229 break; 230 case KTR_USER: 231 type = "USER"; 232 break; 233 default: 234 (void)sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type); 235 type = unknown; 236 } 237 238 if (kth->ktr_tid || (kth->ktr_flags & KTRH_THREADED) || fixedformat) 239 col = printf("%5d:%-4d", kth->ktr_pid, kth->ktr_tid); 240 else 241 col = printf("%5d", kth->ktr_pid); 242 col += printf(" %-8.*s ", MAXCOMLEN, kth->ktr_comm); 243 if (timestamp) { 244 if (timestamp == 2) { 245 temp = kth->ktr_time; 246 timevalsub(&kth->ktr_time, &prevtime); 247 prevtime = temp; 248 } 249 col += printf("%ld.%06ld ", 250 kth->ktr_time.tv_sec, kth->ktr_time.tv_usec); 251 } 252 col += printf("%s ", type); 253 return col; 254 } 255 256 #include <sys/syscall.h> 257 #define KTRACE 258 #include <sys/kern/syscalls.c> 259 #undef KTRACE 260 int nsyscalls = sizeof (syscallnames) / sizeof (syscallnames[0]); 261 262 static const char *ptrace_ops[] = { 263 "PT_TRACE_ME", "PT_READ_I", "PT_READ_D", "PT_READ_U", 264 "PT_WRITE_I", "PT_WRITE_D", "PT_WRITE_U", "PT_CONTINUE", 265 "PT_KILL", "PT_STEP", "PT_ATTACH", "PT_DETACH", 266 }; 267 268 static void 269 ktrsyscall(struct ktr_syscall *ktr) 270 { 271 int narg = ktr->ktr_narg; 272 register_t *ip; 273 274 if (ktr->ktr_code >= nsyscalls || ktr->ktr_code < 0) 275 (void)printf("[%d]", ktr->ktr_code); 276 else 277 (void)printf("%s", syscallnames[ktr->ktr_code]); 278 ip = &ktr->ktr_args[0]; 279 if (narg) { 280 char c = '('; 281 if (fancy) { 282 283 #define print_number(i,n,c) do { \ 284 if (decimal) \ 285 (void)printf("%c%ld", c, (long)*i); \ 286 else \ 287 (void)printf("%c%#lx", c, (long)*i); \ 288 i++; \ 289 n--; \ 290 c = ','; \ 291 } while (0); 292 293 if (ktr->ktr_code == SYS_ioctl) { 294 const char *cp; 295 print_number(ip,narg,c); 296 if ((cp = ioctlname(*ip)) != NULL) 297 (void)printf(",%s", cp); 298 else { 299 if (decimal) 300 (void)printf(",%ld", (long)*ip); 301 else 302 (void)printf(",%#lx ", (long)*ip); 303 } 304 c = ','; 305 ip++; 306 narg--; 307 } else if (ktr->ktr_code == SYS_access) { 308 print_number(ip,narg,c); 309 (void)putchar(','); 310 accessmodename ((int)*ip); 311 ip++; 312 narg--; 313 } else if (ktr->ktr_code == SYS_open || 314 ktr->ktr_code == SYS_mq_open) { 315 int flags; 316 int mode; 317 print_number(ip,narg,c); 318 flags = *ip; 319 mode = *++ip; 320 (void)putchar(','); 321 flagsandmodename (flags, mode, decimal); 322 ip++; 323 narg-=2; 324 } else if (ktr->ktr_code == SYS_wait4) { 325 print_number(ip,narg,c); 326 print_number(ip,narg,c); 327 (void)putchar(','); 328 wait4optname ((int)*ip); 329 ip++; 330 narg--; 331 } else if (ktr->ktr_code == SYS_chmod || 332 ktr->ktr_code == SYS_fchmod || 333 ktr->ktr_code == SYS_lchmod) { 334 print_number(ip,narg,c); 335 (void)putchar(','); 336 modename ((int)*ip); 337 ip++; 338 narg--; 339 } else if (ktr->ktr_code == SYS_mknod) { 340 print_number(ip,narg,c); 341 (void)putchar(','); 342 modename ((int)*ip); 343 ip++; 344 narg--; 345 } else if (ktr->ktr_code == SYS_getfsstat) { 346 print_number(ip,narg,c); 347 print_number(ip,narg,c); 348 (void)putchar(','); 349 getfsstatflagsname ((int)*ip); 350 ip++; 351 narg--; 352 } else if (ktr->ktr_code == SYS_mount) { 353 print_number(ip,narg,c); 354 print_number(ip,narg,c); 355 (void)putchar(','); 356 mountflagsname ((int)*ip); 357 ip++; 358 narg--; 359 } else if (ktr->ktr_code == SYS_unmount) { 360 print_number(ip,narg,c); 361 (void)putchar(','); 362 mountflagsname ((int)*ip); 363 ip++; 364 narg--; 365 } else if (ktr->ktr_code == SYS_recvmsg || 366 ktr->ktr_code == SYS_sendmsg) { 367 print_number(ip,narg,c); 368 print_number(ip,narg,c); 369 (void)putchar(','); 370 sendrecvflagsname ((int)*ip); 371 ip++; 372 narg--; 373 } else if (ktr->ktr_code == SYS_recvfrom || 374 ktr->ktr_code == SYS_sendto) { 375 print_number(ip,narg,c); 376 print_number(ip,narg,c); 377 print_number(ip,narg,c); 378 (void)putchar(','); 379 sendrecvflagsname ((int)*ip); 380 ip++; 381 narg--; 382 } else if (ktr->ktr_code == SYS_chflags || 383 ktr->ktr_code == SYS_fchflags) { 384 print_number(ip,narg,c); 385 (void)putchar(','); 386 modename((int)*ip); 387 ip++; 388 narg--; 389 } else if (ktr->ktr_code == SYS_kill) { 390 print_number(ip,narg,c); 391 (void)putchar(','); 392 signame((int)*ip); 393 ip++; 394 narg--; 395 } else if (ktr->ktr_code == SYS_reboot) { 396 (void)putchar('('); 397 rebootoptname((int)*ip); 398 ip++; 399 narg--; 400 } else if (ktr->ktr_code == SYS_umask) { 401 (void)putchar('('); 402 modename((int)*ip); 403 ip++; 404 narg--; 405 } else if (ktr->ktr_code == SYS_msync) { 406 print_number(ip,narg,c); 407 print_number(ip,narg,c); 408 (void)putchar(','); 409 msyncflagsname((int)*ip); 410 ip++; 411 narg--; 412 } else if (ktr->ktr_code == SYS_mmap) { 413 print_number(ip,narg,c); 414 print_number(ip,narg,c); 415 (void)putchar(','); 416 mmapprotname ((int)*ip); 417 (void)putchar(','); 418 ip++; 419 narg--; 420 mmapflagsname ((int)*ip); 421 ip++; 422 narg--; 423 } else if (ktr->ktr_code == SYS_mprotect) { 424 print_number(ip,narg,c); 425 print_number(ip,narg,c); 426 (void)putchar(','); 427 mmapprotname ((int)*ip); 428 ip++; 429 narg--; 430 } else if (ktr->ktr_code == SYS_madvise) { 431 print_number(ip,narg,c); 432 print_number(ip,narg,c); 433 (void)putchar(','); 434 madvisebehavname((int)*ip); 435 ip++; 436 narg--; 437 } else if (ktr->ktr_code == SYS_setpriority) { 438 (void)putchar('('); 439 prioname((int)*ip); 440 ip++; 441 narg--; 442 c = ','; 443 print_number(ip,narg,c); 444 print_number(ip,narg,c); 445 } else if (ktr->ktr_code == SYS_fcntl) { 446 int cmd; 447 int arg; 448 print_number(ip,narg,c); 449 cmd = *ip; 450 arg = *++ip; 451 (void)putchar(','); 452 fcntlcmdname(cmd, arg, decimal); 453 ip++; 454 narg-=2; 455 } else if (ktr->ktr_code == SYS_socket) { 456 (void)putchar('('); 457 sockdomainname((int)*ip); 458 ip++; 459 narg--; 460 (void)putchar(','); 461 socktypename((int)*ip); 462 ip++; 463 narg--; 464 c = ','; 465 } else if (ktr->ktr_code == SYS_setsockopt || 466 ktr->ktr_code == SYS_getsockopt) { 467 print_number(ip,narg,c); 468 (void)putchar(','); 469 sockoptlevelname((int)*ip, decimal); 470 ip++; 471 narg--; 472 (void)putchar(','); 473 sockoptname((int)*ip); 474 ip++; 475 narg--; 476 } else if (ktr->ktr_code == SYS_lseek) { 477 print_number(ip,narg,c); 478 /* Hidden 'pad' argument, not in lseek(2) */ 479 print_number(ip,narg,c); 480 print_number(ip,narg,c); 481 (void)putchar(','); 482 whencename ((int)*ip); 483 ip++; 484 narg--; 485 } else if (ktr->ktr_code == SYS_flock) { 486 print_number(ip,narg,c); 487 (void)putchar(','); 488 flockname((int)*ip); 489 ip++; 490 narg--; 491 } else if (ktr->ktr_code == SYS_mkfifo || 492 ktr->ktr_code == SYS_mkdir) { 493 print_number(ip,narg,c); 494 (void)putchar(','); 495 modename((int)*ip); 496 ip++; 497 narg--; 498 } else if (ktr->ktr_code == SYS_shutdown) { 499 print_number(ip,narg,c); 500 (void)putchar(','); 501 shutdownhowname((int)*ip); 502 ip++; 503 narg--; 504 } else if (ktr->ktr_code == SYS_socketpair) { 505 (void)putchar('('); 506 sockdomainname((int)*ip); 507 ip++; 508 narg--; 509 (void)putchar(','); 510 socktypename((int)*ip); 511 ip++; 512 narg--; 513 c = ','; 514 } else if (ktr->ktr_code == SYS_getrlimit || 515 ktr->ktr_code == SYS_setrlimit) { 516 (void)putchar('('); 517 rlimitname((int)*ip); 518 ip++; 519 narg--; 520 c = ','; 521 } else if (ktr->ktr_code == SYS_quotactl) { 522 print_number(ip,narg,c); 523 quotactlname((int)*ip); 524 ip++; 525 narg--; 526 c = ','; 527 } else if (ktr->ktr_code == SYS_rtprio) { 528 (void)putchar('('); 529 rtprioname((int)*ip); 530 ip++; 531 narg--; 532 c = ','; 533 } else if (ktr->ktr_code == SYS___semctl) { 534 print_number(ip,narg,c); 535 print_number(ip,narg,c); 536 semctlname((int)*ip); 537 ip++; 538 narg--; 539 } else if (ktr->ktr_code == SYS_semget) { 540 print_number(ip,narg,c); 541 print_number(ip,narg,c); 542 semgetname((int)*ip); 543 ip++; 544 narg--; 545 } else if (ktr->ktr_code == SYS_msgctl) { 546 print_number(ip,narg,c); 547 shmctlname((int)*ip); 548 ip++; 549 narg--; 550 } else if (ktr->ktr_code == SYS_shmat) { 551 print_number(ip,narg,c); 552 print_number(ip,narg,c); 553 shmatname((int)*ip); 554 ip++; 555 narg--; 556 } else if (ktr->ktr_code == SYS_shmctl) { 557 print_number(ip,narg,c); 558 shmctlname((int)*ip); 559 ip++; 560 narg--; 561 } else if (ktr->ktr_code == SYS_minherit) { 562 print_number(ip,narg,c); 563 print_number(ip,narg,c); 564 minheritname((int)*ip); 565 ip++; 566 narg--; 567 } else if (ktr->ktr_code == SYS_rfork) { 568 (void)putchar('('); 569 rforkname((int)*ip); 570 ip++; 571 narg--; 572 c = ','; 573 } else if (ktr->ktr_code == SYS_lio_listio) { 574 (void)putchar('('); 575 lio_listioname((int)*ip); 576 ip++; 577 narg--; 578 c = ','; 579 } else if (ktr->ktr_code == SYS_mlockall) { 580 (void)putchar('('); 581 mlockallname((int)*ip); 582 ip++; 583 narg--; 584 } else if (ktr->ktr_code == SYS_sched_setscheduler) { 585 print_number(ip,narg,c); 586 schedpolicyname((int)*ip); 587 ip++; 588 narg--; 589 } else if (ktr->ktr_code == SYS_sched_get_priority_max || 590 ktr->ktr_code == SYS_sched_get_priority_min) { 591 (void)putchar('('); 592 schedpolicyname((int)*ip); 593 ip++; 594 narg--; 595 } else if (ktr->ktr_code == SYS_sendfile) { 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 print_number(ip,narg,c); 602 sendfileflagsname((int)*ip); 603 ip++; 604 narg--; 605 } else if (ktr->ktr_code == SYS_kldsym) { 606 print_number(ip,narg,c); 607 kldsymcmdname((int)*ip); 608 ip++; 609 narg--; 610 } else if (ktr->ktr_code == SYS_sigprocmask) { 611 (void)putchar('('); 612 sigprocmaskhowname((int)*ip); 613 ip++; 614 narg--; 615 c = ','; 616 } else if (ktr->ktr_code == SYS___acl_get_file || 617 ktr->ktr_code == SYS___acl_set_file || 618 ktr->ktr_code == SYS___acl_get_fd || 619 ktr->ktr_code == SYS___acl_set_fd || 620 ktr->ktr_code == SYS___acl_delete_file || 621 ktr->ktr_code == SYS___acl_delete_fd || 622 ktr->ktr_code == SYS___acl_aclcheck_file || 623 ktr->ktr_code == SYS___acl_aclcheck_fd) { 624 print_number(ip,narg,c); 625 acltypename((int)*ip); 626 ip++; 627 narg--; 628 } else if (ktr->ktr_code == SYS_sigaction) { 629 (void)putchar('('); 630 signame((int)*ip); 631 ip++; 632 narg--; 633 c = ','; 634 } else if (ktr->ktr_code == SYS_extattrctl) { 635 print_number(ip,narg,c); 636 extattrctlname((int)*ip); 637 ip++; 638 narg--; 639 } else if (ktr->ktr_code == SYS_ptrace) { 640 if (*ip < (register_t)(sizeof(ptrace_ops) / 641 sizeof(ptrace_ops[0])) && *ip >= 0) 642 (void)printf("(%s", ptrace_ops[*ip]); 643 #ifdef PT_GETREGS 644 else if (*ip == PT_GETREGS) 645 (void)printf("(%s", "PT_GETREGS"); 646 #endif 647 #ifdef PT_SETREGS 648 else if (*ip == PT_SETREGS) 649 (void)printf("(%s", "PT_SETREGS"); 650 #endif 651 #ifdef PT_GETFPREGS 652 else if (*ip == PT_GETFPREGS) 653 (void)printf("(%s", "PT_GETFPREGS"); 654 #endif 655 #ifdef PT_SETFPREGS 656 else if (*ip == PT_SETFPREGS) 657 (void)printf("(%s", "PT_SETFPREGS"); 658 #endif 659 #ifdef PT_GETDBREGS 660 else if (*ip == PT_GETDBREGS) 661 (void)printf("(%s", "PT_GETDBREGS"); 662 #endif 663 #ifdef PT_SETDBREGS 664 else if (*ip == PT_SETDBREGS) 665 (void)printf("(%s", "PT_SETDBREGS"); 666 #endif 667 else 668 (void)printf("(%ld", (long)*ip); 669 c = ','; 670 ip++; 671 narg--; 672 } 673 } 674 while (narg > 0) { 675 print_number(ip,narg,c); 676 } 677 (void)putchar(')'); 678 } 679 (void)putchar('\n'); 680 } 681 682 static void 683 ktrsysret(struct ktr_sysret *ktr) 684 { 685 register_t ret = ktr->ktr_retval; 686 int error = ktr->ktr_error; 687 int code = ktr->ktr_code; 688 689 if (code >= nsyscalls || code < 0) 690 (void)printf("[%d] ", code); 691 else 692 (void)printf("%s ", syscallnames[code]); 693 694 if (error == 0) { 695 if (fancy) { 696 (void)printf("%ld", (long)ret); 697 if (ret < 0 || ret > 9) 698 (void)printf("/%#lx", (long)ret); 699 } else { 700 if (decimal) 701 (void)printf("%ld", (long)ret); 702 else 703 (void)printf("%#lx", (long)ret); 704 } 705 } else if (error == ERESTART) 706 (void)printf("RESTART"); 707 else if (error == EJUSTRETURN) 708 (void)printf("JUSTRETURN"); 709 else { 710 (void)printf("-1 errno %d", ktr->ktr_error); 711 if (fancy) 712 (void)printf(" %s", strerror(ktr->ktr_error)); 713 } 714 (void)putchar('\n'); 715 } 716 717 static void 718 ktrnamei(char *cp, int len) 719 { 720 (void)printf("\"%.*s\"\n", len, cp); 721 } 722 723 static void 724 ktrgenio(struct ktr_genio *ktr, int len) 725 { 726 int datalen = len - sizeof (struct ktr_genio); 727 char *dp = (char *)ktr + sizeof (struct ktr_genio); 728 char *cp; 729 int col = 0; 730 int width; 731 char visbuf[5]; 732 static int screenwidth = 0; 733 734 if (screenwidth == 0) { 735 struct winsize ws; 736 737 if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 && 738 ws.ws_col > 8) 739 screenwidth = ws.ws_col; 740 else 741 screenwidth = 80; 742 } 743 printf("fd %d %s %d byte%s\n", ktr->ktr_fd, 744 ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen, 745 datalen == 1 ? "" : "s"); 746 if (maxdata && datalen > maxdata) 747 datalen = maxdata; 748 (void)printf(" \""); 749 col = 8; 750 for (;datalen > 0; datalen--, dp++) { 751 (void) vis(visbuf, *dp, VIS_CSTYLE, *(dp+1)); 752 cp = visbuf; 753 /* 754 * Keep track of printables and 755 * space chars (like fold(1)). 756 */ 757 if (col == 0) { 758 (void)putchar('\t'); 759 col = 8; 760 } 761 switch(*cp) { 762 case '\n': 763 col = 0; 764 (void)putchar('\n'); 765 continue; 766 case '\t': 767 width = 8 - (col&07); 768 break; 769 default: 770 width = strlen(cp); 771 } 772 if (col + width > (screenwidth-2)) { 773 (void)printf("\\\n\t"); 774 col = 8; 775 } 776 col += width; 777 do { 778 (void)putchar(*cp++); 779 } while (*cp); 780 } 781 if (col == 0) 782 (void)printf(" "); 783 (void)printf("\"\n"); 784 } 785 786 const char *signames[NSIG] = { 787 "NULL", "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT", /* 1 - 6 */ 788 "EMT", "FPE", "KILL", "BUS", "SEGV", "SYS", /* 7 - 12 */ 789 "PIPE", "ALRM", "TERM", "URG", "STOP", "TSTP", /* 13 - 18 */ 790 "CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU", /* 19 - 24 */ 791 "XFSZ", "VTALRM", "PROF", "WINCH", "29", "USR1", /* 25 - 30 */ 792 "USR2", NULL, /* 31 - 32 */ 793 }; 794 795 static void 796 ktrpsig(struct ktr_psig *psig) 797 { 798 (void)printf("SIG%s ", signames[psig->signo]); 799 if (psig->action == SIG_DFL) 800 (void)printf("SIG_DFL\n"); 801 else 802 (void)printf("caught handler=0x%lx mask=0x%x code=0x%x\n", 803 (u_long)psig->action, psig->mask.__bits[0], psig->code); 804 } 805 806 static void 807 ktrcsw(struct ktr_csw *cs) 808 { 809 (void)printf("%s %s\n", cs->out ? "stop" : "resume", 810 cs->user ? "user" : "kernel"); 811 } 812 813 #define UTRACE_DLOPEN_START 1 814 #define UTRACE_DLOPEN_STOP 2 815 #define UTRACE_DLCLOSE_START 3 816 #define UTRACE_DLCLOSE_STOP 4 817 #define UTRACE_LOAD_OBJECT 5 818 #define UTRACE_UNLOAD_OBJECT 6 819 #define UTRACE_ADD_RUNDEP 7 820 #define UTRACE_PRELOAD_FINISHED 8 821 #define UTRACE_INIT_CALL 9 822 #define UTRACE_FINI_CALL 10 823 824 struct utrace_rtld { 825 char sig[4]; /* 'RTLD' */ 826 int event; 827 void *handle; 828 void *mapbase; 829 size_t mapsize; 830 int refcnt; 831 char name[MAXPATHLEN]; 832 }; 833 834 static void 835 ktruser_rtld(int len, unsigned char *p) 836 { 837 struct utrace_rtld *ut = (struct utrace_rtld *)p; 838 void *parent; 839 int mode; 840 841 switch (ut->event) { 842 case UTRACE_DLOPEN_START: 843 mode = ut->refcnt; 844 printf("dlopen(%s, ", ut->name); 845 switch (mode & RTLD_MODEMASK) { 846 case RTLD_NOW: 847 printf("RTLD_NOW"); 848 break; 849 case RTLD_LAZY: 850 printf("RTLD_LAZY"); 851 break; 852 default: 853 printf("%#x", mode & RTLD_MODEMASK); 854 } 855 if (mode & RTLD_GLOBAL) 856 printf(" | RTLD_GLOBAL"); 857 if (mode & RTLD_TRACE) 858 printf(" | RTLD_TRACE"); 859 if (mode & ~(RTLD_MODEMASK | RTLD_GLOBAL | RTLD_TRACE)) 860 printf(" | %#x", mode & 861 ~(RTLD_MODEMASK | RTLD_GLOBAL | RTLD_TRACE)); 862 printf(")\n"); 863 break; 864 case UTRACE_DLOPEN_STOP: 865 printf("%p = dlopen(%s) ref %d\n", ut->handle, ut->name, 866 ut->refcnt); 867 break; 868 case UTRACE_DLCLOSE_START: 869 printf("dlclose(%p) (%s, %d)\n", ut->handle, ut->name, 870 ut->refcnt); 871 break; 872 case UTRACE_DLCLOSE_STOP: 873 printf("dlclose(%p) finished\n", ut->handle); 874 break; 875 case UTRACE_LOAD_OBJECT: 876 printf("RTLD: loaded %p @ %p - %p (%s)\n", ut->handle, 877 ut->mapbase, (char *)ut->mapbase + ut->mapsize - 1, 878 ut->name); 879 break; 880 case UTRACE_UNLOAD_OBJECT: 881 printf("RTLD: unloaded %p @ %p - %p (%s)\n", ut->handle, 882 ut->mapbase, (char *)ut->mapbase + ut->mapsize - 1, 883 ut->name); 884 break; 885 case UTRACE_ADD_RUNDEP: 886 parent = ut->mapbase; 887 printf("RTLD: %p now depends on %p (%s, %d)\n", parent, 888 ut->handle, ut->name, ut->refcnt); 889 break; 890 case UTRACE_PRELOAD_FINISHED: 891 printf("RTLD: LD_PRELOAD finished\n"); 892 break; 893 case UTRACE_INIT_CALL: 894 printf("RTLD: init %p for %p (%s)\n", ut->mapbase, ut->handle, 895 ut->name); 896 break; 897 case UTRACE_FINI_CALL: 898 printf("RTLD: fini %p for %p (%s)\n", ut->mapbase, ut->handle, 899 ut->name); 900 break; 901 default: 902 p += 4; 903 len -= 4; 904 printf("RTLD: %d ", len); 905 while (len--) 906 if (decimal) 907 printf(" %d", *p++); 908 else 909 printf(" %02x", *p++); 910 printf("\n"); 911 } 912 } 913 914 struct utrace_malloc { 915 void *p; 916 size_t s; 917 void *r; 918 }; 919 920 static void 921 ktruser_malloc(int len __unused, unsigned char *p) 922 { 923 struct utrace_malloc *ut = (struct utrace_malloc *)p; 924 925 if (ut->p == NULL) { 926 if (ut->s == 0 && ut->r == NULL) 927 printf("malloc_init()\n"); 928 else 929 printf("%p = malloc(%zu)\n", ut->r, ut->s); 930 } else { 931 if (ut->s == 0) 932 printf("free(%p)\n", ut->p); 933 else 934 printf("%p = realloc(%p, %zu)\n", ut->r, ut->p, ut->s); 935 } 936 } 937 938 static void 939 ktruser(int len, unsigned char *p) 940 { 941 942 if (len >= 8 && bcmp(p, "RTLD", 4) == 0) { 943 ktruser_rtld(len, p); 944 return; 945 } 946 947 if (len == sizeof(struct utrace_malloc)) { 948 ktruser_malloc(len, p); 949 return; 950 } 951 952 (void)printf("%d ", len); 953 while (len--) 954 (void)printf(" %02x", *p++); 955 (void)printf("\n"); 956 } 957 958 static void 959 usage(void) 960 { 961 (void)fprintf(stderr, 962 "usage: kdump [-dnlRT] [-f trfile] [-m maxdata] [-t [cnisuw]] [-p pid]\n"); 963 exit(1); 964 } 965 966 static void 967 timevalsub(struct timeval *t1, struct timeval *t2) 968 { 969 t1->tv_sec -= t2->tv_sec; 970 t1->tv_usec -= t2->tv_usec; 971 timevalfix(t1); 972 } 973 974 static void 975 timevalfix(struct timeval *t1) 976 { 977 if (t1->tv_usec < 0) { 978 t1->tv_sec--; 979 t1->tv_usec += 1000000; 980 } 981 if (t1->tv_usec >= 1000000) { 982 t1->tv_sec++; 983 t1->tv_usec -= 1000000; 984 } 985 } 986