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