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