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 * 4. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #ifndef lint 31 static const char copyright[] = 32 "@(#) Copyright (c) 1988, 1993\n\ 33 The Regents of the University of California. All rights reserved.\n"; 34 #endif /* not lint */ 35 36 #ifndef lint 37 #if 0 38 static char sccsid[] = "@(#)kdump.c 8.1 (Berkeley) 6/6/93"; 39 #endif 40 #endif /* not lint */ 41 #include <sys/cdefs.h> 42 __FBSDID("$FreeBSD$"); 43 44 #define _KERNEL 45 extern int errno; 46 #include <sys/errno.h> 47 #undef _KERNEL 48 #include <sys/param.h> 49 #include <sys/errno.h> 50 #define _KERNEL 51 #include <sys/time.h> 52 #undef _KERNEL 53 #include <sys/uio.h> 54 #include <sys/ktrace.h> 55 #include <sys/ioctl.h> 56 #include <sys/socket.h> 57 #include <sys/stat.h> 58 #include <sys/un.h> 59 #ifdef IPX 60 #include <sys/types.h> 61 #include <netipx/ipx.h> 62 #endif 63 #ifdef NETATALK 64 #include <netatalk/at.h> 65 #endif 66 #include <arpa/inet.h> 67 #include <netinet/in.h> 68 #include <ctype.h> 69 #include <dlfcn.h> 70 #include <err.h> 71 #include <grp.h> 72 #include <inttypes.h> 73 #include <locale.h> 74 #include <pwd.h> 75 #include <stdio.h> 76 #include <stdlib.h> 77 #include <string.h> 78 #include <time.h> 79 #include <unistd.h> 80 #include <vis.h> 81 #include "ktrace.h" 82 #include "kdump_subr.h" 83 84 int fread_tail(void *, int, int); 85 void dumpheader(struct ktr_header *); 86 void ktrsyscall(struct ktr_syscall *); 87 void ktrsysret(struct ktr_sysret *); 88 void ktrnamei(char *, int); 89 void hexdump(char *, int, int); 90 void visdump(char *, int, int); 91 void ktrgenio(struct ktr_genio *, int); 92 void ktrpsig(struct ktr_psig *); 93 void ktrcsw(struct ktr_csw *); 94 void ktruser(int, unsigned char *); 95 void ktrsockaddr(struct sockaddr *); 96 void ktrstat(struct stat *); 97 void ktrstruct(char *, size_t); 98 void usage(void); 99 void sockfamilyname(int); 100 const char *ioctlname(u_long); 101 102 int timestamp, decimal, fancy = 1, suppressdata, tail, threads, maxdata, 103 resolv = 0; 104 const char *tracefile = DEF_TRACEFILE; 105 struct ktr_header ktr_header; 106 107 #define TIME_FORMAT "%b %e %T %Y" 108 #define eqs(s1, s2) (strcmp((s1), (s2)) == 0) 109 110 int 111 main(int argc, char *argv[]) 112 { 113 int ch, ktrlen, size; 114 void *m; 115 int trpoints = ALL_POINTS; 116 int drop_logged; 117 pid_t pid = 0; 118 119 (void) setlocale(LC_CTYPE, ""); 120 121 while ((ch = getopt(argc,argv,"f:dElm:np:HRrsTt:")) != -1) 122 switch((char)ch) { 123 case 'f': 124 tracefile = optarg; 125 break; 126 case 'd': 127 decimal = 1; 128 break; 129 case 'l': 130 tail = 1; 131 break; 132 case 'm': 133 maxdata = atoi(optarg); 134 break; 135 case 'n': 136 fancy = 0; 137 break; 138 case 'p': 139 pid = atoi(optarg); 140 break; 141 case 'r': 142 resolv = 1; 143 break; 144 case 's': 145 suppressdata = 1; 146 break; 147 case 'E': 148 timestamp = 3; /* elapsed timestamp */ 149 break; 150 case 'H': 151 threads = 1; 152 break; 153 case 'R': 154 timestamp = 2; /* relative timestamp */ 155 break; 156 case 'T': 157 timestamp = 1; 158 break; 159 case 't': 160 trpoints = getpoints(optarg); 161 if (trpoints < 0) 162 errx(1, "unknown trace point in %s", optarg); 163 break; 164 default: 165 usage(); 166 } 167 168 if (argc > optind) 169 usage(); 170 171 m = (void *)malloc(size = 1025); 172 if (m == NULL) 173 errx(1, "%s", strerror(ENOMEM)); 174 if (!freopen(tracefile, "r", stdin)) 175 err(1, "%s", tracefile); 176 drop_logged = 0; 177 while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) { 178 if (ktr_header.ktr_type & KTR_DROP) { 179 ktr_header.ktr_type &= ~KTR_DROP; 180 if (!drop_logged && threads) { 181 (void)printf( 182 "%6jd %6jd %-8.*s Events dropped.\n", 183 (intmax_t)ktr_header.ktr_pid, 184 ktr_header.ktr_tid > 0 ? 185 (intmax_t)ktr_header.ktr_tid : 0, 186 MAXCOMLEN, ktr_header.ktr_comm); 187 drop_logged = 1; 188 } else if (!drop_logged) { 189 (void)printf("%6jd %-8.*s Events dropped.\n", 190 (intmax_t)ktr_header.ktr_pid, MAXCOMLEN, 191 ktr_header.ktr_comm); 192 drop_logged = 1; 193 } 194 } 195 if (trpoints & (1<<ktr_header.ktr_type)) 196 if (pid == 0 || ktr_header.ktr_pid == pid) 197 dumpheader(&ktr_header); 198 if ((ktrlen = ktr_header.ktr_len) < 0) 199 errx(1, "bogus length 0x%x", ktrlen); 200 if (ktrlen > size) { 201 m = (void *)realloc(m, ktrlen+1); 202 if (m == NULL) 203 errx(1, "%s", strerror(ENOMEM)); 204 size = ktrlen; 205 } 206 if (ktrlen && fread_tail(m, ktrlen, 1) == 0) 207 errx(1, "data too short"); 208 if (pid && ktr_header.ktr_pid != pid) 209 continue; 210 if ((trpoints & (1<<ktr_header.ktr_type)) == 0) 211 continue; 212 drop_logged = 0; 213 switch (ktr_header.ktr_type) { 214 case KTR_SYSCALL: 215 ktrsyscall((struct ktr_syscall *)m); 216 break; 217 case KTR_SYSRET: 218 ktrsysret((struct ktr_sysret *)m); 219 break; 220 case KTR_NAMEI: 221 case KTR_SYSCTL: 222 ktrnamei(m, ktrlen); 223 break; 224 case KTR_GENIO: 225 ktrgenio((struct ktr_genio *)m, ktrlen); 226 break; 227 case KTR_PSIG: 228 ktrpsig((struct ktr_psig *)m); 229 break; 230 case KTR_CSW: 231 ktrcsw((struct ktr_csw *)m); 232 break; 233 case KTR_USER: 234 ktruser(ktrlen, m); 235 break; 236 case KTR_STRUCT: 237 ktrstruct(m, ktrlen); 238 break; 239 default: 240 printf("\n"); 241 break; 242 } 243 if (tail) 244 (void)fflush(stdout); 245 } 246 return 0; 247 } 248 249 int 250 fread_tail(void *buf, int size, int num) 251 { 252 int i; 253 254 while ((i = fread(buf, size, num, stdin)) == 0 && tail) { 255 (void)sleep(1); 256 clearerr(stdin); 257 } 258 return (i); 259 } 260 261 void 262 dumpheader(struct ktr_header *kth) 263 { 264 static char unknown[64]; 265 static struct timeval prevtime, temp; 266 const char *type; 267 268 switch (kth->ktr_type) { 269 case KTR_SYSCALL: 270 type = "CALL"; 271 break; 272 case KTR_SYSRET: 273 type = "RET "; 274 break; 275 case KTR_NAMEI: 276 type = "NAMI"; 277 break; 278 case KTR_GENIO: 279 type = "GIO "; 280 break; 281 case KTR_PSIG: 282 type = "PSIG"; 283 break; 284 case KTR_CSW: 285 type = "CSW "; 286 break; 287 case KTR_USER: 288 type = "USER"; 289 break; 290 case KTR_STRUCT: 291 type = "STRU"; 292 break; 293 case KTR_SYSCTL: 294 type = "SCTL"; 295 break; 296 default: 297 (void)sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type); 298 type = unknown; 299 } 300 301 /* 302 * The ktr_tid field was previously the ktr_buffer field, which held 303 * the kernel pointer value for the buffer associated with data 304 * following the record header. It now holds a threadid, but only 305 * for trace files after the change. Older trace files still contain 306 * kernel pointers. Detect this and suppress the results by printing 307 * negative tid's as 0. 308 */ 309 if (threads) 310 (void)printf("%6jd %6jd %-8.*s ", (intmax_t)kth->ktr_pid, 311 kth->ktr_tid > 0 ? (intmax_t)kth->ktr_tid : 0, 312 MAXCOMLEN, kth->ktr_comm); 313 else 314 (void)printf("%6jd %-8.*s ", (intmax_t)kth->ktr_pid, MAXCOMLEN, 315 kth->ktr_comm); 316 if (timestamp) { 317 if (timestamp == 3) { 318 if (prevtime.tv_sec == 0) 319 prevtime = kth->ktr_time; 320 timevalsub(&kth->ktr_time, &prevtime); 321 } 322 if (timestamp == 2) { 323 temp = kth->ktr_time; 324 timevalsub(&kth->ktr_time, &prevtime); 325 prevtime = temp; 326 } 327 (void)printf("%jd.%06ld ", (intmax_t)kth->ktr_time.tv_sec, 328 kth->ktr_time.tv_usec); 329 } 330 (void)printf("%s ", type); 331 } 332 333 #include <sys/syscall.h> 334 #define KTRACE 335 #include <sys/kern/syscalls.c> 336 #undef KTRACE 337 int nsyscalls = sizeof (syscallnames) / sizeof (syscallnames[0]); 338 339 void 340 ktrsyscall(struct ktr_syscall *ktr) 341 { 342 int narg = ktr->ktr_narg; 343 register_t *ip; 344 345 if (ktr->ktr_code >= nsyscalls || ktr->ktr_code < 0) 346 (void)printf("[%d]", ktr->ktr_code); 347 else 348 (void)printf("%s", syscallnames[ktr->ktr_code]); 349 ip = &ktr->ktr_args[0]; 350 if (narg) { 351 char c = '('; 352 if (fancy) { 353 354 #define print_number(i,n,c) do { \ 355 if (decimal) \ 356 (void)printf("%c%ld", c, (long)*i); \ 357 else \ 358 (void)printf("%c%#lx", c, (long)*i); \ 359 i++; \ 360 n--; \ 361 c = ','; \ 362 } while (0); 363 364 if (ktr->ktr_code == SYS_ioctl) { 365 const char *cp; 366 print_number(ip,narg,c); 367 if ((cp = ioctlname(*ip)) != NULL) 368 (void)printf(",%s", cp); 369 else { 370 if (decimal) 371 (void)printf(",%ld", (long)*ip); 372 else 373 (void)printf(",%#lx ", (long)*ip); 374 } 375 c = ','; 376 ip++; 377 narg--; 378 } else if (ktr->ktr_code == SYS_ptrace) { 379 (void)putchar('('); 380 ptraceopname ((int)*ip); 381 c = ','; 382 ip++; 383 narg--; 384 } else if (ktr->ktr_code == SYS_access || 385 ktr->ktr_code == SYS_eaccess) { 386 print_number(ip,narg,c); 387 (void)putchar(','); 388 accessmodename ((int)*ip); 389 ip++; 390 narg--; 391 } else if (ktr->ktr_code == SYS_open) { 392 int flags; 393 int mode; 394 print_number(ip,narg,c); 395 flags = *ip; 396 mode = *++ip; 397 (void)putchar(','); 398 flagsandmodename (flags, mode, decimal); 399 ip++; 400 narg-=2; 401 } else if (ktr->ktr_code == SYS_wait4) { 402 print_number(ip,narg,c); 403 print_number(ip,narg,c); 404 (void)putchar(','); 405 wait4optname ((int)*ip); 406 ip++; 407 narg--; 408 } else if (ktr->ktr_code == SYS_chmod || 409 ktr->ktr_code == SYS_fchmod || 410 ktr->ktr_code == SYS_lchmod) { 411 print_number(ip,narg,c); 412 (void)putchar(','); 413 modename ((int)*ip); 414 ip++; 415 narg--; 416 } else if (ktr->ktr_code == SYS_mknod) { 417 print_number(ip,narg,c); 418 (void)putchar(','); 419 modename ((int)*ip); 420 ip++; 421 narg--; 422 } else if (ktr->ktr_code == SYS_getfsstat) { 423 print_number(ip,narg,c); 424 print_number(ip,narg,c); 425 (void)putchar(','); 426 getfsstatflagsname ((int)*ip); 427 ip++; 428 narg--; 429 } else if (ktr->ktr_code == SYS_mount) { 430 print_number(ip,narg,c); 431 print_number(ip,narg,c); 432 (void)putchar(','); 433 mountflagsname ((int)*ip); 434 ip++; 435 narg--; 436 } else if (ktr->ktr_code == SYS_unmount) { 437 print_number(ip,narg,c); 438 (void)putchar(','); 439 mountflagsname ((int)*ip); 440 ip++; 441 narg--; 442 } else if (ktr->ktr_code == SYS_recvmsg || 443 ktr->ktr_code == SYS_sendmsg) { 444 print_number(ip,narg,c); 445 print_number(ip,narg,c); 446 (void)putchar(','); 447 sendrecvflagsname ((int)*ip); 448 ip++; 449 narg--; 450 } else if (ktr->ktr_code == SYS_recvfrom || 451 ktr->ktr_code == SYS_sendto) { 452 print_number(ip,narg,c); 453 print_number(ip,narg,c); 454 print_number(ip,narg,c); 455 (void)putchar(','); 456 sendrecvflagsname ((int)*ip); 457 ip++; 458 narg--; 459 } else if (ktr->ktr_code == SYS_chflags || 460 ktr->ktr_code == SYS_fchflags || 461 ktr->ktr_code == SYS_lchflags) { 462 print_number(ip,narg,c); 463 (void)putchar(','); 464 modename((int)*ip); 465 ip++; 466 narg--; 467 } else if (ktr->ktr_code == SYS_kill) { 468 print_number(ip,narg,c); 469 (void)putchar(','); 470 signame((int)*ip); 471 ip++; 472 narg--; 473 } else if (ktr->ktr_code == SYS_reboot) { 474 (void)putchar('('); 475 rebootoptname((int)*ip); 476 ip++; 477 narg--; 478 } else if (ktr->ktr_code == SYS_umask) { 479 (void)putchar('('); 480 modename((int)*ip); 481 ip++; 482 narg--; 483 } else if (ktr->ktr_code == SYS_msync) { 484 print_number(ip,narg,c); 485 print_number(ip,narg,c); 486 (void)putchar(','); 487 msyncflagsname((int)*ip); 488 ip++; 489 narg--; 490 #ifdef SYS_freebsd6_mmap 491 } else if (ktr->ktr_code == SYS_freebsd6_mmap) { 492 print_number(ip,narg,c); 493 print_number(ip,narg,c); 494 (void)putchar(','); 495 mmapprotname ((int)*ip); 496 (void)putchar(','); 497 ip++; 498 narg--; 499 mmapflagsname ((int)*ip); 500 ip++; 501 narg--; 502 #endif 503 } else if (ktr->ktr_code == SYS_mmap) { 504 print_number(ip,narg,c); 505 print_number(ip,narg,c); 506 (void)putchar(','); 507 mmapprotname ((int)*ip); 508 (void)putchar(','); 509 ip++; 510 narg--; 511 mmapflagsname ((int)*ip); 512 ip++; 513 narg--; 514 } else if (ktr->ktr_code == SYS_mprotect) { 515 print_number(ip,narg,c); 516 print_number(ip,narg,c); 517 (void)putchar(','); 518 mmapprotname ((int)*ip); 519 ip++; 520 narg--; 521 } else if (ktr->ktr_code == SYS_madvise) { 522 print_number(ip,narg,c); 523 print_number(ip,narg,c); 524 (void)putchar(','); 525 madvisebehavname((int)*ip); 526 ip++; 527 narg--; 528 } else if (ktr->ktr_code == SYS_setpriority) { 529 print_number(ip,narg,c); 530 print_number(ip,narg,c); 531 (void)putchar(','); 532 prioname((int)*ip); 533 ip++; 534 narg--; 535 } else if (ktr->ktr_code == SYS_fcntl) { 536 int cmd; 537 int arg; 538 print_number(ip,narg,c); 539 cmd = *ip; 540 arg = *++ip; 541 (void)putchar(','); 542 fcntlcmdname(cmd, arg, decimal); 543 ip++; 544 narg-=2; 545 } else if (ktr->ktr_code == SYS_socket) { 546 int sockdomain; 547 (void)putchar('('); 548 sockdomain=(int)*ip; 549 sockdomainname(sockdomain); 550 ip++; 551 narg--; 552 (void)putchar(','); 553 socktypename((int)*ip); 554 ip++; 555 narg--; 556 if (sockdomain == PF_INET || 557 sockdomain == PF_INET6) { 558 (void)putchar(','); 559 sockipprotoname((int)*ip); 560 ip++; 561 narg--; 562 } 563 c = ','; 564 } else if (ktr->ktr_code == SYS_setsockopt || 565 ktr->ktr_code == SYS_getsockopt) { 566 print_number(ip,narg,c); 567 (void)putchar(','); 568 sockoptlevelname((int)*ip, decimal); 569 if ((int)*ip == SOL_SOCKET) { 570 ip++; 571 narg--; 572 (void)putchar(','); 573 sockoptname((int)*ip); 574 } 575 ip++; 576 narg--; 577 #ifdef SYS_freebsd6_lseek 578 } else if (ktr->ktr_code == SYS_freebsd6_lseek) { 579 print_number(ip,narg,c); 580 /* Hidden 'pad' argument, not in lseek(2) */ 581 print_number(ip,narg,c); 582 print_number(ip,narg,c); 583 (void)putchar(','); 584 whencename ((int)*ip); 585 ip++; 586 narg--; 587 #endif 588 } else if (ktr->ktr_code == SYS_lseek) { 589 print_number(ip,narg,c); 590 /* Hidden 'pad' argument, not in lseek(2) */ 591 print_number(ip,narg,c); 592 (void)putchar(','); 593 whencename ((int)*ip); 594 ip++; 595 narg--; 596 597 } else if (ktr->ktr_code == SYS_flock) { 598 print_number(ip,narg,c); 599 (void)putchar(','); 600 flockname((int)*ip); 601 ip++; 602 narg--; 603 } else if (ktr->ktr_code == SYS_mkfifo || 604 ktr->ktr_code == SYS_mkdir) { 605 print_number(ip,narg,c); 606 (void)putchar(','); 607 modename((int)*ip); 608 ip++; 609 narg--; 610 } else if (ktr->ktr_code == SYS_shutdown) { 611 print_number(ip,narg,c); 612 (void)putchar(','); 613 shutdownhowname((int)*ip); 614 ip++; 615 narg--; 616 } else if (ktr->ktr_code == SYS_socketpair) { 617 (void)putchar('('); 618 sockdomainname((int)*ip); 619 ip++; 620 narg--; 621 (void)putchar(','); 622 socktypename((int)*ip); 623 ip++; 624 narg--; 625 c = ','; 626 } else if (ktr->ktr_code == SYS_getrlimit || 627 ktr->ktr_code == SYS_setrlimit) { 628 (void)putchar('('); 629 rlimitname((int)*ip); 630 ip++; 631 narg--; 632 c = ','; 633 } else if (ktr->ktr_code == SYS_quotactl) { 634 print_number(ip,narg,c); 635 (void)putchar(','); 636 quotactlname((int)*ip); 637 ip++; 638 narg--; 639 c = ','; 640 } else if (ktr->ktr_code == SYS_nfssvc) { 641 (void)putchar('('); 642 nfssvcname((int)*ip); 643 ip++; 644 narg--; 645 c = ','; 646 } else if (ktr->ktr_code == SYS_rtprio) { 647 (void)putchar('('); 648 rtprioname((int)*ip); 649 ip++; 650 narg--; 651 c = ','; 652 } else if (ktr->ktr_code == SYS___semctl) { 653 print_number(ip,narg,c); 654 print_number(ip,narg,c); 655 (void)putchar(','); 656 semctlname((int)*ip); 657 ip++; 658 narg--; 659 } else if (ktr->ktr_code == SYS_semget) { 660 print_number(ip,narg,c); 661 print_number(ip,narg,c); 662 (void)putchar(','); 663 semgetname((int)*ip); 664 ip++; 665 narg--; 666 } else if (ktr->ktr_code == SYS_msgctl) { 667 print_number(ip,narg,c); 668 (void)putchar(','); 669 shmctlname((int)*ip); 670 ip++; 671 narg--; 672 } else if (ktr->ktr_code == SYS_shmat) { 673 print_number(ip,narg,c); 674 print_number(ip,narg,c); 675 (void)putchar(','); 676 shmatname((int)*ip); 677 ip++; 678 narg--; 679 } else if (ktr->ktr_code == SYS_shmctl) { 680 print_number(ip,narg,c); 681 (void)putchar(','); 682 shmctlname((int)*ip); 683 ip++; 684 narg--; 685 } else if (ktr->ktr_code == SYS_minherit) { 686 print_number(ip,narg,c); 687 print_number(ip,narg,c); 688 (void)putchar(','); 689 minheritname((int)*ip); 690 ip++; 691 narg--; 692 } else if (ktr->ktr_code == SYS_rfork) { 693 (void)putchar('('); 694 rforkname((int)*ip); 695 ip++; 696 narg--; 697 c = ','; 698 } else if (ktr->ktr_code == SYS_lio_listio) { 699 (void)putchar('('); 700 lio_listioname((int)*ip); 701 ip++; 702 narg--; 703 c = ','; 704 } else if (ktr->ktr_code == SYS_mlockall) { 705 (void)putchar('('); 706 mlockallname((int)*ip); 707 ip++; 708 narg--; 709 } else if (ktr->ktr_code == SYS_sched_setscheduler) { 710 print_number(ip,narg,c); 711 (void)putchar(','); 712 schedpolicyname((int)*ip); 713 ip++; 714 narg--; 715 } else if (ktr->ktr_code == SYS_sched_get_priority_max || 716 ktr->ktr_code == SYS_sched_get_priority_min) { 717 (void)putchar('('); 718 schedpolicyname((int)*ip); 719 ip++; 720 narg--; 721 } else if (ktr->ktr_code == SYS_sendfile) { 722 print_number(ip,narg,c); 723 print_number(ip,narg,c); 724 print_number(ip,narg,c); 725 print_number(ip,narg,c); 726 print_number(ip,narg,c); 727 print_number(ip,narg,c); 728 (void)putchar(','); 729 sendfileflagsname((int)*ip); 730 ip++; 731 narg--; 732 } else if (ktr->ktr_code == SYS_kldsym) { 733 print_number(ip,narg,c); 734 (void)putchar(','); 735 kldsymcmdname((int)*ip); 736 ip++; 737 narg--; 738 } else if (ktr->ktr_code == SYS_sigprocmask) { 739 (void)putchar('('); 740 sigprocmaskhowname((int)*ip); 741 ip++; 742 narg--; 743 c = ','; 744 } else if (ktr->ktr_code == SYS___acl_get_file || 745 ktr->ktr_code == SYS___acl_set_file || 746 ktr->ktr_code == SYS___acl_get_fd || 747 ktr->ktr_code == SYS___acl_set_fd || 748 ktr->ktr_code == SYS___acl_delete_file || 749 ktr->ktr_code == SYS___acl_delete_fd || 750 ktr->ktr_code == SYS___acl_aclcheck_file || 751 ktr->ktr_code == SYS___acl_aclcheck_fd || 752 ktr->ktr_code == SYS___acl_get_link || 753 ktr->ktr_code == SYS___acl_set_link || 754 ktr->ktr_code == SYS___acl_delete_link || 755 ktr->ktr_code == SYS___acl_aclcheck_link) { 756 print_number(ip,narg,c); 757 (void)putchar(','); 758 acltypename((int)*ip); 759 ip++; 760 narg--; 761 } else if (ktr->ktr_code == SYS_sigaction) { 762 (void)putchar('('); 763 signame((int)*ip); 764 ip++; 765 narg--; 766 c = ','; 767 } else if (ktr->ktr_code == SYS_extattrctl) { 768 print_number(ip,narg,c); 769 (void)putchar(','); 770 extattrctlname((int)*ip); 771 ip++; 772 narg--; 773 } else if (ktr->ktr_code == SYS_nmount) { 774 print_number(ip,narg,c); 775 print_number(ip,narg,c); 776 (void)putchar(','); 777 mountflagsname ((int)*ip); 778 ip++; 779 narg--; 780 } else if (ktr->ktr_code == SYS_thr_create) { 781 print_number(ip,narg,c); 782 print_number(ip,narg,c); 783 (void)putchar(','); 784 thrcreateflagsname ((int)*ip); 785 ip++; 786 narg--; 787 } else if (ktr->ktr_code == SYS_thr_kill) { 788 print_number(ip,narg,c); 789 (void)putchar(','); 790 signame ((int)*ip); 791 ip++; 792 narg--; 793 } else if (ktr->ktr_code == SYS_kldunloadf) { 794 print_number(ip,narg,c); 795 (void)putchar(','); 796 kldunloadfflagsname ((int)*ip); 797 ip++; 798 narg--; 799 } 800 } 801 while (narg > 0) { 802 print_number(ip,narg,c); 803 } 804 (void)putchar(')'); 805 } 806 (void)putchar('\n'); 807 } 808 809 void 810 ktrsysret(struct ktr_sysret *ktr) 811 { 812 register_t ret = ktr->ktr_retval; 813 int error = ktr->ktr_error; 814 int code = ktr->ktr_code; 815 816 if (code >= nsyscalls || code < 0) 817 (void)printf("[%d] ", code); 818 else 819 (void)printf("%s ", syscallnames[code]); 820 821 if (error == 0) { 822 if (fancy) { 823 (void)printf("%ld", (long)ret); 824 if (ret < 0 || ret > 9) 825 (void)printf("/%#lx", (long)ret); 826 } else { 827 if (decimal) 828 (void)printf("%ld", (long)ret); 829 else 830 (void)printf("%#lx", (long)ret); 831 } 832 } else if (error == ERESTART) 833 (void)printf("RESTART"); 834 else if (error == EJUSTRETURN) 835 (void)printf("JUSTRETURN"); 836 else { 837 (void)printf("-1 errno %d", ktr->ktr_error); 838 if (fancy) 839 (void)printf(" %s", strerror(ktr->ktr_error)); 840 } 841 (void)putchar('\n'); 842 } 843 844 void 845 ktrnamei(char *cp, int len) 846 { 847 (void)printf("\"%.*s\"\n", len, cp); 848 } 849 850 void 851 hexdump(char *p, int len, int screenwidth) 852 { 853 int n, i; 854 int width; 855 856 width = 0; 857 do { 858 width += 2; 859 i = 13; /* base offset */ 860 i += (width / 2) + 1; /* spaces every second byte */ 861 i += (width * 2); /* width of bytes */ 862 i += 3; /* " |" */ 863 i += width; /* each byte */ 864 i += 1; /* "|" */ 865 } while (i < screenwidth); 866 width -= 2; 867 868 for (n = 0; n < len; n += width) { 869 for (i = n; i < n + width; i++) { 870 if ((i % width) == 0) { /* beginning of line */ 871 printf(" 0x%04x", i); 872 } 873 if ((i % 2) == 0) { 874 printf(" "); 875 } 876 if (i < len) 877 printf("%02x", p[i] & 0xff); 878 else 879 printf(" "); 880 } 881 printf(" |"); 882 for (i = n; i < n + width; i++) { 883 if (i >= len) 884 break; 885 if (p[i] >= ' ' && p[i] <= '~') 886 printf("%c", p[i]); 887 else 888 printf("."); 889 } 890 printf("|\n"); 891 } 892 if ((i % width) != 0) 893 printf("\n"); 894 } 895 896 void 897 visdump(char *dp, int datalen, int screenwidth) 898 { 899 int col = 0; 900 char *cp; 901 int width; 902 char visbuf[5]; 903 904 (void)printf(" \""); 905 col = 8; 906 for (;datalen > 0; datalen--, dp++) { 907 (void) vis(visbuf, *dp, VIS_CSTYLE, *(dp+1)); 908 cp = visbuf; 909 /* 910 * Keep track of printables and 911 * space chars (like fold(1)). 912 */ 913 if (col == 0) { 914 (void)putchar('\t'); 915 col = 8; 916 } 917 switch(*cp) { 918 case '\n': 919 col = 0; 920 (void)putchar('\n'); 921 continue; 922 case '\t': 923 width = 8 - (col&07); 924 break; 925 default: 926 width = strlen(cp); 927 } 928 if (col + width > (screenwidth-2)) { 929 (void)printf("\\\n\t"); 930 col = 8; 931 } 932 col += width; 933 do { 934 (void)putchar(*cp++); 935 } while (*cp); 936 } 937 if (col == 0) 938 (void)printf(" "); 939 (void)printf("\"\n"); 940 } 941 942 void 943 ktrgenio(struct ktr_genio *ktr, int len) 944 { 945 int datalen = len - sizeof (struct ktr_genio); 946 char *dp = (char *)ktr + sizeof (struct ktr_genio); 947 static int screenwidth = 0; 948 int i, binary; 949 950 if (screenwidth == 0) { 951 struct winsize ws; 952 953 if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 && 954 ws.ws_col > 8) 955 screenwidth = ws.ws_col; 956 else 957 screenwidth = 80; 958 } 959 printf("fd %d %s %d byte%s\n", ktr->ktr_fd, 960 ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen, 961 datalen == 1 ? "" : "s"); 962 if (suppressdata) 963 return; 964 if (maxdata && datalen > maxdata) 965 datalen = maxdata; 966 967 for (i = 0, binary = 0; i < datalen && binary == 0; i++) { 968 if (dp[i] >= 32 && dp[i] < 127) 969 continue; 970 if (dp[i] == 10 || dp[i] == 13 || dp[i] == 0 || dp[i] == 9) 971 continue; 972 binary = 1; 973 } 974 if (binary) 975 hexdump(dp, datalen, screenwidth); 976 else 977 visdump(dp, datalen, screenwidth); 978 } 979 980 const char *signames[] = { 981 "NULL", "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT", /* 1 - 6 */ 982 "EMT", "FPE", "KILL", "BUS", "SEGV", "SYS", /* 7 - 12 */ 983 "PIPE", "ALRM", "TERM", "URG", "STOP", "TSTP", /* 13 - 18 */ 984 "CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU", /* 19 - 24 */ 985 "XFSZ", "VTALRM", "PROF", "WINCH", "29", "USR1", /* 25 - 30 */ 986 "USR2", NULL, /* 31 - 32 */ 987 }; 988 989 void 990 ktrpsig(struct ktr_psig *psig) 991 { 992 if (psig->signo > 0 && psig->signo < NSIG) 993 (void)printf("SIG%s ", signames[psig->signo]); 994 else 995 (void)printf("SIG %d ", psig->signo); 996 if (psig->action == SIG_DFL) 997 (void)printf("SIG_DFL\n"); 998 else { 999 (void)printf("caught handler=0x%lx mask=0x%x code=0x%x\n", 1000 (u_long)psig->action, psig->mask.__bits[0], psig->code); 1001 } 1002 } 1003 1004 void 1005 ktrcsw(struct ktr_csw *cs) 1006 { 1007 (void)printf("%s %s\n", cs->out ? "stop" : "resume", 1008 cs->user ? "user" : "kernel"); 1009 } 1010 1011 #define UTRACE_DLOPEN_START 1 1012 #define UTRACE_DLOPEN_STOP 2 1013 #define UTRACE_DLCLOSE_START 3 1014 #define UTRACE_DLCLOSE_STOP 4 1015 #define UTRACE_LOAD_OBJECT 5 1016 #define UTRACE_UNLOAD_OBJECT 6 1017 #define UTRACE_ADD_RUNDEP 7 1018 #define UTRACE_PRELOAD_FINISHED 8 1019 #define UTRACE_INIT_CALL 9 1020 #define UTRACE_FINI_CALL 10 1021 1022 struct utrace_rtld { 1023 char sig[4]; /* 'RTLD' */ 1024 int event; 1025 void *handle; 1026 void *mapbase; 1027 size_t mapsize; 1028 int refcnt; 1029 char name[MAXPATHLEN]; 1030 }; 1031 1032 void 1033 ktruser_rtld(int len, unsigned char *p) 1034 { 1035 struct utrace_rtld *ut = (struct utrace_rtld *)p; 1036 void *parent; 1037 int mode; 1038 1039 switch (ut->event) { 1040 case UTRACE_DLOPEN_START: 1041 mode = ut->refcnt; 1042 printf("dlopen(%s, ", ut->name); 1043 switch (mode & RTLD_MODEMASK) { 1044 case RTLD_NOW: 1045 printf("RTLD_NOW"); 1046 break; 1047 case RTLD_LAZY: 1048 printf("RTLD_LAZY"); 1049 break; 1050 default: 1051 printf("%#x", mode & RTLD_MODEMASK); 1052 } 1053 if (mode & RTLD_GLOBAL) 1054 printf(" | RTLD_GLOBAL"); 1055 if (mode & RTLD_TRACE) 1056 printf(" | RTLD_TRACE"); 1057 if (mode & ~(RTLD_MODEMASK | RTLD_GLOBAL | RTLD_TRACE)) 1058 printf(" | %#x", mode & 1059 ~(RTLD_MODEMASK | RTLD_GLOBAL | RTLD_TRACE)); 1060 printf(")\n"); 1061 break; 1062 case UTRACE_DLOPEN_STOP: 1063 printf("%p = dlopen(%s) ref %d\n", ut->handle, ut->name, 1064 ut->refcnt); 1065 break; 1066 case UTRACE_DLCLOSE_START: 1067 printf("dlclose(%p) (%s, %d)\n", ut->handle, ut->name, 1068 ut->refcnt); 1069 break; 1070 case UTRACE_DLCLOSE_STOP: 1071 printf("dlclose(%p) finished\n", ut->handle); 1072 break; 1073 case UTRACE_LOAD_OBJECT: 1074 printf("RTLD: loaded %p @ %p - %p (%s)\n", ut->handle, 1075 ut->mapbase, (char *)ut->mapbase + ut->mapsize - 1, 1076 ut->name); 1077 break; 1078 case UTRACE_UNLOAD_OBJECT: 1079 printf("RTLD: unloaded %p @ %p - %p (%s)\n", ut->handle, 1080 ut->mapbase, (char *)ut->mapbase + ut->mapsize - 1, 1081 ut->name); 1082 break; 1083 case UTRACE_ADD_RUNDEP: 1084 parent = ut->mapbase; 1085 printf("RTLD: %p now depends on %p (%s, %d)\n", parent, 1086 ut->handle, ut->name, ut->refcnt); 1087 break; 1088 case UTRACE_PRELOAD_FINISHED: 1089 printf("RTLD: LD_PRELOAD finished\n"); 1090 break; 1091 case UTRACE_INIT_CALL: 1092 printf("RTLD: init %p for %p (%s)\n", ut->mapbase, ut->handle, 1093 ut->name); 1094 break; 1095 case UTRACE_FINI_CALL: 1096 printf("RTLD: fini %p for %p (%s)\n", ut->mapbase, ut->handle, 1097 ut->name); 1098 break; 1099 default: 1100 p += 4; 1101 len -= 4; 1102 printf("RTLD: %d ", len); 1103 while (len--) 1104 if (decimal) 1105 printf(" %d", *p++); 1106 else 1107 printf(" %02x", *p++); 1108 printf("\n"); 1109 } 1110 } 1111 1112 struct utrace_malloc { 1113 void *p; 1114 size_t s; 1115 void *r; 1116 }; 1117 1118 void 1119 ktruser_malloc(int len, unsigned char *p) 1120 { 1121 struct utrace_malloc *ut = (struct utrace_malloc *)p; 1122 1123 if (ut->p == (void *)(intptr_t)(-1)) 1124 printf("malloc_init()\n"); 1125 else if (ut->s == 0) 1126 printf("free(%p)\n", ut->p); 1127 else if (ut->p == NULL) 1128 printf("%p = malloc(%zu)\n", ut->r, ut->s); 1129 else 1130 printf("%p = realloc(%p, %zu)\n", ut->r, ut->p, ut->s); 1131 } 1132 1133 void 1134 ktruser(int len, unsigned char *p) 1135 { 1136 1137 if (len >= 8 && bcmp(p, "RTLD", 4) == 0) { 1138 ktruser_rtld(len, p); 1139 return; 1140 } 1141 1142 if (len == sizeof(struct utrace_malloc)) { 1143 ktruser_malloc(len, p); 1144 return; 1145 } 1146 1147 (void)printf("%d ", len); 1148 while (len--) 1149 if (decimal) 1150 (void)printf(" %d", *p++); 1151 else 1152 (void)printf(" %02x", *p++); 1153 (void)printf("\n"); 1154 } 1155 1156 void 1157 ktrsockaddr(struct sockaddr *sa) 1158 { 1159 /* 1160 TODO: Support additional address families 1161 #include <netnatm/natm.h> 1162 struct sockaddr_natm *natm; 1163 #include <netsmb/netbios.h> 1164 struct sockaddr_nb *nb; 1165 */ 1166 char addr[64]; 1167 1168 /* 1169 * note: ktrstruct() has already verified that sa points to a 1170 * buffer at least sizeof(struct sockaddr) bytes long and exactly 1171 * sa->sa_len bytes long. 1172 */ 1173 printf("struct sockaddr { "); 1174 sockfamilyname(sa->sa_family); 1175 printf(", "); 1176 1177 #define check_sockaddr_len(n) \ 1178 if (sa_##n->s##n##_len < sizeof(struct sockaddr_##n)) { \ 1179 printf("invalid"); \ 1180 break; \ 1181 } 1182 1183 switch(sa->sa_family) { 1184 case AF_INET: { 1185 struct sockaddr_in *sa_in; 1186 1187 sa_in = (struct sockaddr_in *)sa; 1188 check_sockaddr_len(in); 1189 inet_ntop(AF_INET, &sa_in->sin_addr, addr, sizeof addr); 1190 printf("%s:%u", addr, ntohs(sa_in->sin_port)); 1191 break; 1192 } 1193 #ifdef NETATALK 1194 case AF_APPLETALK: { 1195 struct sockaddr_at *sa_at; 1196 struct netrange *nr; 1197 1198 sa_at = (struct sockaddr_at *)sa; 1199 check_sockaddr_len(at); 1200 nr = &sa_at->sat_range.r_netrange; 1201 printf("%d.%d, %d-%d, %d", ntohs(sa_at->sat_addr.s_net), 1202 sa_at->sat_addr.s_node, ntohs(nr->nr_firstnet), 1203 ntohs(nr->nr_lastnet), nr->nr_phase); 1204 break; 1205 } 1206 #endif 1207 case AF_INET6: { 1208 struct sockaddr_in6 *sa_in6; 1209 1210 sa_in6 = (struct sockaddr_in6 *)sa; 1211 check_sockaddr_len(in6); 1212 inet_ntop(AF_INET6, &sa_in6->sin6_addr, addr, sizeof addr); 1213 printf("[%s]:%u", addr, htons(sa_in6->sin6_port)); 1214 break; 1215 } 1216 #ifdef IPX 1217 case AF_IPX: { 1218 struct sockaddr_ipx *sa_ipx; 1219 1220 sa_ipx = (struct sockaddr_ipx *)sa; 1221 check_sockaddr_len(ipx); 1222 /* XXX wish we had ipx_ntop */ 1223 printf("%s", ipx_ntoa(sa_ipx->sipx_addr)); 1224 break; 1225 } 1226 #endif 1227 case AF_UNIX: { 1228 struct sockaddr_un *sa_un; 1229 1230 sa_un = (struct sockaddr_un *)sa; 1231 check_sockaddr_len(un); 1232 printf("%.*s", (int)sizeof(sa_un->sun_path), sa_un->sun_path); 1233 break; 1234 } 1235 default: 1236 printf("unknown address family"); 1237 } 1238 printf(" }\n"); 1239 } 1240 1241 void 1242 ktrstat(struct stat *statp) 1243 { 1244 char mode[12], timestr[PATH_MAX + 4]; 1245 struct passwd *pwd; 1246 struct group *grp; 1247 struct tm *tm; 1248 1249 /* 1250 * note: ktrstruct() has already verified that statp points to a 1251 * buffer exactly sizeof(struct stat) bytes long. 1252 */ 1253 printf("struct stat {"); 1254 strmode(statp->st_mode, mode); 1255 printf("dev=%ju, ino=%ju, mode=%s, nlink=%ju, ", 1256 (uintmax_t)statp->st_dev, (uintmax_t)statp->st_ino, mode, 1257 (uintmax_t)statp->st_nlink); 1258 if (resolv == 0 || (pwd = getpwuid(statp->st_uid)) == NULL) 1259 printf("uid=%ju, ", (uintmax_t)statp->st_uid); 1260 else 1261 printf("uid=\"%s\", ", pwd->pw_name); 1262 if (resolv == 0 || (grp = getgrgid(statp->st_gid)) == NULL) 1263 printf("gid=%ju, ", (uintmax_t)statp->st_gid); 1264 else 1265 printf("gid=\"%s\", ", grp->gr_name); 1266 printf("rdev=%ju, ", (uintmax_t)statp->st_rdev); 1267 printf("atime="); 1268 if (resolv == 0) 1269 printf("%jd", (intmax_t)statp->st_atim.tv_sec); 1270 else { 1271 tm = localtime(&statp->st_atim.tv_sec); 1272 (void)strftime(timestr, sizeof(timestr), TIME_FORMAT, tm); 1273 printf("\"%s\"", timestr); 1274 } 1275 if (statp->st_atim.tv_nsec != 0) 1276 printf(".%09ld, ", statp->st_atim.tv_nsec); 1277 else 1278 printf(", "); 1279 printf("stime="); 1280 if (resolv == 0) 1281 printf("%jd", (intmax_t)statp->st_mtim.tv_sec); 1282 else { 1283 tm = localtime(&statp->st_mtim.tv_sec); 1284 (void)strftime(timestr, sizeof(timestr), TIME_FORMAT, tm); 1285 printf("\"%s\"", timestr); 1286 } 1287 if (statp->st_mtim.tv_nsec != 0) 1288 printf(".%09ld, ", statp->st_mtim.tv_nsec); 1289 else 1290 printf(", "); 1291 printf("ctime="); 1292 if (resolv == 0) 1293 printf("%jd", (intmax_t)statp->st_ctim.tv_sec); 1294 else { 1295 tm = localtime(&statp->st_ctim.tv_sec); 1296 (void)strftime(timestr, sizeof(timestr), TIME_FORMAT, tm); 1297 printf("\"%s\"", timestr); 1298 } 1299 if (statp->st_ctim.tv_nsec != 0) 1300 printf(".%09ld, ", statp->st_ctim.tv_nsec); 1301 else 1302 printf(", "); 1303 printf("birthtime="); 1304 if (resolv == 0) 1305 printf("%jd", (intmax_t)statp->st_birthtim.tv_sec); 1306 else { 1307 tm = localtime(&statp->st_birthtim.tv_sec); 1308 (void)strftime(timestr, sizeof(timestr), TIME_FORMAT, tm); 1309 printf("\"%s\"", timestr); 1310 } 1311 if (statp->st_birthtim.tv_nsec != 0) 1312 printf(".%09ld, ", statp->st_birthtim.tv_nsec); 1313 else 1314 printf(", "); 1315 printf("size=%jd, blksize=%ju, blocks=%jd, flags=0x%x", 1316 (uintmax_t)statp->st_size, (uintmax_t)statp->st_blksize, 1317 (intmax_t)statp->st_blocks, statp->st_flags); 1318 printf(" }\n"); 1319 } 1320 1321 void 1322 ktrstruct(char *buf, size_t buflen) 1323 { 1324 char *name, *data; 1325 size_t namelen, datalen; 1326 int i; 1327 struct stat sb; 1328 struct sockaddr_storage ss; 1329 1330 for (name = buf, namelen = 0; 1331 namelen < buflen && name[namelen] != '\0'; 1332 ++namelen) 1333 /* nothing */; 1334 if (namelen == buflen) 1335 goto invalid; 1336 if (name[namelen] != '\0') 1337 goto invalid; 1338 data = buf + namelen + 1; 1339 datalen = buflen - namelen - 1; 1340 if (datalen == 0) 1341 goto invalid; 1342 /* sanity check */ 1343 for (i = 0; i < namelen; ++i) 1344 if (!isalpha((unsigned char)name[i])) 1345 goto invalid; 1346 if (strcmp(name, "stat") == 0) { 1347 if (datalen != sizeof(struct stat)) 1348 goto invalid; 1349 memcpy(&sb, data, datalen); 1350 ktrstat(&sb); 1351 } else if (strcmp(name, "sockaddr") == 0) { 1352 if (datalen > sizeof(ss)) 1353 goto invalid; 1354 memcpy(&ss, data, datalen); 1355 if (datalen < sizeof(struct sockaddr) || 1356 datalen != ss.ss_len) 1357 goto invalid; 1358 ktrsockaddr((struct sockaddr *)&ss); 1359 } else { 1360 printf("unknown structure\n"); 1361 } 1362 return; 1363 invalid: 1364 printf("invalid record\n"); 1365 } 1366 1367 void 1368 usage(void) 1369 { 1370 fprintf(stderr, "usage: kdump [-dEnlHRrsT] [-f trfile] " 1371 "[-m maxdata] [-p pid] [-t trstr]\n"); 1372 exit(1); 1373 } 1374