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