1 /* $OpenBSD: kdump.c,v 1.41 2009/10/27 23:59:39 deraadt Exp $ */ 2 3 /*- 4 * Copyright (c) 1988, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/param.h> 33 #include <sys/time.h> 34 #include <sys/uio.h> 35 #include <sys/ktrace.h> 36 #include <sys/ioctl.h> 37 #include <sys/ptrace.h> 38 #include <sys/sysctl.h> 39 #define _KERNEL 40 #include <sys/errno.h> 41 #undef _KERNEL 42 43 #include <ctype.h> 44 #include <err.h> 45 #include <signal.h> 46 #include <stdio.h> 47 #include <stdlib.h> 48 #include <string.h> 49 #include <unistd.h> 50 #include <vis.h> 51 52 #include "ktrace.h" 53 #include "kdump.h" 54 #include "extern.h" 55 56 int timestamp, decimal, iohex, fancy = 1, tail, maxdata; 57 char *tracefile = DEF_TRACEFILE; 58 struct ktr_header ktr_header; 59 pid_t pid = -1; 60 61 #define eqs(s1, s2) (strcmp((s1), (s2)) == 0) 62 63 #include <sys/syscall.h> 64 65 #include <compat/bsdos/bsdos_syscall.h> 66 #include <compat/freebsd/freebsd_syscall.h> 67 #if defined(__hppa__) || defined(__m68k__) 68 #include <compat/hpux/hpux_syscall.h> 69 #endif 70 #include <compat/ibcs2/ibcs2_syscall.h> 71 #include <compat/linux/linux_syscall.h> 72 #include <compat/osf1/osf1_syscall.h> 73 #include <compat/sunos/sunos_syscall.h> 74 #include <compat/svr4/svr4_syscall.h> 75 #include <compat/ultrix/ultrix_syscall.h> 76 77 #define KTRACE 78 #define PTRACE 79 #define NFSCLIENT 80 #define NFSSERVER 81 #define SYSVSEM 82 #define SYSVMSG 83 #define SYSVSHM 84 #define LFS 85 #define RTHREADS 86 #include <kern/syscalls.c> 87 88 #include <compat/bsdos/bsdos_syscalls.c> 89 #include <compat/freebsd/freebsd_syscalls.c> 90 #if defined(__hppa__) || defined(__m68k__) 91 #include <compat/hpux/hpux_syscalls.c> 92 #endif 93 #include <compat/ibcs2/ibcs2_syscalls.c> 94 #include <compat/linux/linux_syscalls.c> 95 #include <compat/osf1/osf1_syscalls.c> 96 #include <compat/sunos/sunos_syscalls.c> 97 #include <compat/svr4/svr4_syscalls.c> 98 #include <compat/ultrix/ultrix_syscalls.c> 99 #undef KTRACE 100 #undef PTRACE 101 #undef NFSCLIENT 102 #undef NFSSERVER 103 #undef SYSVSEM 104 #undef SYSVMSG 105 #undef SYSVSHM 106 #undef LFS 107 #undef RTHREADS 108 109 struct emulation { 110 char *name; /* Emulation name */ 111 char **sysnames; /* Array of system call names */ 112 int nsysnames; /* Number of */ 113 }; 114 115 static struct emulation emulations[] = { 116 { "native", syscallnames, SYS_MAXSYSCALL }, 117 #if defined(__hppa__) || defined(__m68k__) 118 { "hpux", hpux_syscallnames, HPUX_SYS_MAXSYSCALL }, 119 #endif 120 { "ibcs2", ibcs2_syscallnames, IBCS2_SYS_MAXSYSCALL }, 121 { "linux", linux_syscallnames, LINUX_SYS_MAXSYSCALL }, 122 { "osf1", osf1_syscallnames, OSF1_SYS_MAXSYSCALL }, 123 { "sunos", sunos_syscallnames, SUNOS_SYS_MAXSYSCALL }, 124 { "svr4", svr4_syscallnames, SVR4_SYS_MAXSYSCALL }, 125 { "ultrix", ultrix_syscallnames, ULTRIX_SYS_MAXSYSCALL }, 126 { "bsdos", bsdos_syscallnames, BSDOS_SYS_MAXSYSCALL }, 127 { "freebsd", freebsd_syscallnames, FREEBSD_SYS_MAXSYSCALL }, 128 { NULL, NULL, NULL } 129 }; 130 131 struct emulation *current; 132 133 134 static char *ptrace_ops[] = { 135 "PT_TRACE_ME", "PT_READ_I", "PT_READ_D", "PT_READ_U", 136 "PT_WRITE_I", "PT_WRITE_D", "PT_WRITE_U", "PT_CONTINUE", 137 "PT_KILL", "PT_ATTACH", "PT_DETACH", "PT_IO", 138 }; 139 140 static int fread_tail(void *, size_t, size_t); 141 static void dumpheader(struct ktr_header *); 142 static void ktrcsw(struct ktr_csw *); 143 static void ktremul(char *, size_t); 144 static void ktrgenio(struct ktr_genio *, size_t); 145 static void ktrnamei(const char *, size_t); 146 static void ktrpsig(struct ktr_psig *); 147 static void ktrsyscall(struct ktr_syscall *); 148 static void ktrsysret(struct ktr_sysret *); 149 static void setemul(const char *); 150 static void usage(void); 151 152 int 153 main(int argc, char *argv[]) 154 { 155 int ch, silent; 156 size_t ktrlen, size; 157 int trpoints = ALL_POINTS; 158 void *m; 159 160 current = &emulations[0]; /* native */ 161 162 while ((ch = getopt(argc, argv, "e:f:dlm:nRp:Tt:xX")) != -1) 163 switch (ch) { 164 case 'e': 165 setemul(optarg); 166 break; 167 case 'f': 168 tracefile = optarg; 169 break; 170 case 'd': 171 decimal = 1; 172 break; 173 case 'l': 174 tail = 1; 175 break; 176 case 'm': 177 maxdata = atoi(optarg); 178 break; 179 case 'n': 180 fancy = 0; 181 break; 182 case 'p': 183 pid = atoi(optarg); 184 break; 185 case 'R': 186 timestamp = 2; /* relative timestamp */ 187 break; 188 case 'T': 189 timestamp = 1; 190 break; 191 case 't': 192 trpoints = getpoints(optarg); 193 if (trpoints < 0) 194 errx(1, "unknown trace point in %s", optarg); 195 break; 196 case 'x': 197 iohex = 1; 198 break; 199 case 'X': 200 iohex = 2; 201 break; 202 default: 203 usage(); 204 } 205 if (argc > optind) 206 usage(); 207 208 m = malloc(size = 1025); 209 if (m == NULL) 210 err(1, NULL); 211 if (!freopen(tracefile, "r", stdin)) 212 err(1, "%s", tracefile); 213 while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) { 214 silent = 0; 215 if (pid != -1 && pid != ktr_header.ktr_pid) 216 silent = 1; 217 if (silent == 0 && trpoints & (1<<ktr_header.ktr_type)) 218 dumpheader(&ktr_header); 219 ktrlen = ktr_header.ktr_len; 220 if (ktrlen > size) { 221 void *newm; 222 223 newm = realloc(m, ktrlen+1); 224 if (newm == NULL) 225 err(1, NULL); 226 m = newm; 227 size = ktrlen; 228 } 229 if (ktrlen && fread_tail(m, ktrlen, 1) == 0) 230 errx(1, "data too short"); 231 if (silent) 232 continue; 233 if ((trpoints & (1<<ktr_header.ktr_type)) == 0) 234 continue; 235 switch (ktr_header.ktr_type) { 236 case KTR_SYSCALL: 237 ktrsyscall((struct ktr_syscall *)m); 238 break; 239 case KTR_SYSRET: 240 ktrsysret((struct ktr_sysret *)m); 241 break; 242 case KTR_NAMEI: 243 ktrnamei(m, ktrlen); 244 break; 245 case KTR_GENIO: 246 ktrgenio((struct ktr_genio *)m, ktrlen); 247 break; 248 case KTR_PSIG: 249 ktrpsig((struct ktr_psig *)m); 250 break; 251 case KTR_CSW: 252 ktrcsw((struct ktr_csw *)m); 253 break; 254 case KTR_EMUL: 255 ktremul(m, ktrlen); 256 break; 257 } 258 if (tail) 259 (void)fflush(stdout); 260 } 261 exit(0); 262 } 263 264 static int 265 fread_tail(void *buf, size_t size, size_t num) 266 { 267 int i; 268 269 while ((i = fread(buf, size, num, stdin)) == 0 && tail) { 270 (void)sleep(1); 271 clearerr(stdin); 272 } 273 return (i); 274 } 275 276 static void 277 dumpheader(struct ktr_header *kth) 278 { 279 static struct timeval prevtime; 280 char unknown[64], *type; 281 struct timeval temp; 282 283 switch (kth->ktr_type) { 284 case KTR_SYSCALL: 285 type = "CALL"; 286 break; 287 case KTR_SYSRET: 288 type = "RET "; 289 break; 290 case KTR_NAMEI: 291 type = "NAMI"; 292 break; 293 case KTR_GENIO: 294 type = "GIO "; 295 break; 296 case KTR_PSIG: 297 type = "PSIG"; 298 break; 299 case KTR_CSW: 300 type = "CSW"; 301 break; 302 case KTR_EMUL: 303 type = "EMUL"; 304 break; 305 default: 306 (void)snprintf(unknown, sizeof unknown, "UNKNOWN(%d)", 307 kth->ktr_type); 308 type = unknown; 309 } 310 311 (void)printf("%6ld %-8.*s ", (long)kth->ktr_pid, MAXCOMLEN, 312 kth->ktr_comm); 313 if (timestamp) { 314 if (timestamp == 2) { 315 timersub(&kth->ktr_time, &prevtime, &temp); 316 prevtime = kth->ktr_time; 317 } else 318 temp = kth->ktr_time; 319 (void)printf("%ld.%06ld ", temp.tv_sec, temp.tv_usec); 320 } 321 (void)printf("%s ", type); 322 } 323 324 static void 325 ioctldecode(u_long cmd) 326 { 327 char dirbuf[4], *dir = dirbuf; 328 329 if (cmd & IOC_IN) 330 *dir++ = 'W'; 331 if (cmd & IOC_OUT) 332 *dir++ = 'R'; 333 *dir = '\0'; 334 335 printf(decimal ? ",_IO%s('%c',%lu" : ",_IO%s('%c',%#lx", 336 dirbuf, (int)((cmd >> 8) & 0xff), cmd & 0xff); 337 if ((cmd & IOC_VOID) == 0) 338 printf(decimal ? ",%lu)" : ",%#lx)", (cmd >> 16) & 0xff); 339 else 340 printf(")"); 341 } 342 343 static void 344 ktrsyscall(struct ktr_syscall *ktr) 345 { 346 int argsize = ktr->ktr_argsize; 347 register_t *ap; 348 349 if (ktr->ktr_code >= current->nsysnames || ktr->ktr_code < 0) 350 (void)printf("[%d]", ktr->ktr_code); 351 else 352 (void)printf("%s", current->sysnames[ktr->ktr_code]); 353 ap = (register_t *)((char *)ktr + sizeof(struct ktr_syscall)); 354 (void)putchar('('); 355 if (argsize) { 356 char c = '\0'; 357 if (fancy) { 358 if (ktr->ktr_code == SYS_ioctl) { 359 const char *cp; 360 361 if (decimal) 362 (void)printf("%ld", (long)*ap); 363 else 364 (void)printf("%#lx", (long)*ap); 365 ap++; 366 argsize -= sizeof(register_t); 367 if ((cp = ioctlname(*ap)) != NULL) 368 (void)printf(",%s", cp); 369 else 370 ioctldecode(*ap); 371 c = ','; 372 ap++; 373 argsize -= sizeof(register_t); 374 } else if (ktr->ktr_code == SYS___sysctl) { 375 int *np, n; 376 377 n = ap[1]; 378 if (n > CTL_MAXNAME) 379 n = CTL_MAXNAME; 380 np = (int *)(ap + 6); 381 for (; n--; np++) { 382 if (c) 383 putchar(c); 384 printf("%d", *np); 385 c = '.'; 386 } 387 388 c = ','; 389 ap += 2; 390 argsize -= 2 * sizeof(register_t); 391 } else if (ktr->ktr_code == SYS_ptrace) { 392 if (*ap >= 0 && *ap < 393 sizeof(ptrace_ops) / sizeof(ptrace_ops[0])) 394 (void)printf("%s", ptrace_ops[*ap]); 395 else switch(*ap) { 396 #ifdef PT_GETFPREGS 397 case PT_GETFPREGS: 398 (void)printf("PT_GETFPREGS"); 399 break; 400 #endif 401 case PT_GETREGS: 402 (void)printf("PT_GETREGS"); 403 break; 404 #ifdef PT_SETFPREGS 405 case PT_SETFPREGS: 406 (void)printf("PT_SETFPREGS"); 407 break; 408 #endif 409 case PT_SETREGS: 410 (void)printf("PT_SETREGS"); 411 break; 412 #ifdef PT_STEP 413 case PT_STEP: 414 (void)printf("PT_STEP"); 415 break; 416 #endif 417 #ifdef PT_WCOOKIE 418 case PT_WCOOKIE: 419 (void)printf("PT_WCOOKIE"); 420 break; 421 #endif 422 default: 423 (void)printf("%ld", (long)*ap); 424 break; 425 } 426 c = ','; 427 ap++; 428 argsize -= sizeof(register_t); 429 } 430 } 431 while (argsize) { 432 if (c) 433 putchar(c); 434 if (decimal) 435 (void)printf("%ld", (long)*ap); 436 else 437 (void)printf("%#lx", (long)*ap); 438 c = ','; 439 ap++; 440 argsize -= sizeof(register_t); 441 } 442 } 443 (void)printf(")\n"); 444 } 445 446 static void 447 ktrsysret(struct ktr_sysret *ktr) 448 { 449 int ret = ktr->ktr_retval; 450 int error = ktr->ktr_error; 451 int code = ktr->ktr_code; 452 453 if (code >= current->nsysnames || code < 0) 454 (void)printf("[%d] ", code); 455 else 456 (void)printf("%s ", current->sysnames[code]); 457 458 if (error == 0) { 459 if (fancy) { 460 (void)printf("%d", ret); 461 if (ret < 0 || ret > 9) 462 (void)printf("/%#x", ret); 463 } else { 464 if (decimal) 465 (void)printf("%d", ret); 466 else 467 (void)printf("%#x", ret); 468 } 469 } else if (error == ERESTART) 470 (void)printf("RESTART"); 471 else if (error == EJUSTRETURN) 472 (void)printf("JUSTRETURN"); 473 else { 474 (void)printf("-1 errno %d", ktr->ktr_error); 475 if (fancy) 476 (void)printf(" %s", strerror(ktr->ktr_error)); 477 } 478 (void)putchar('\n'); 479 } 480 481 static void 482 ktrnamei(const char *cp, size_t len) 483 { 484 (void)printf("\"%.*s\"\n", (int)len, cp); 485 } 486 487 static void 488 ktremul(char *cp, size_t len) 489 { 490 char name[1024]; 491 492 if (len >= sizeof(name)) 493 errx(1, "Emulation name too long"); 494 495 strncpy(name, cp, len); 496 name[len] = '\0'; 497 (void)printf("\"%s\"\n", name); 498 499 setemul(name); 500 } 501 502 static void 503 ktrgenio(struct ktr_genio *ktr, size_t len) 504 { 505 unsigned char *dp = (unsigned char *)ktr + sizeof(struct ktr_genio); 506 int i, j; 507 size_t datalen = len - sizeof(struct ktr_genio); 508 static int screenwidth = 0; 509 int col = 0, width, bpl; 510 unsigned char visbuf[5], *cp, c; 511 512 if (screenwidth == 0) { 513 struct winsize ws; 514 515 if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 && 516 ws.ws_col > 8) 517 screenwidth = ws.ws_col; 518 else 519 screenwidth = 80; 520 } 521 printf("fd %d %s %zu bytes\n", ktr->ktr_fd, 522 ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen); 523 if (maxdata && datalen > maxdata) 524 datalen = maxdata; 525 if (iohex && !datalen) 526 return; 527 if (iohex == 1) { 528 putchar('\t'); 529 col = 8; 530 for (i = 0; i < datalen; i++) { 531 printf("%02x", dp[i]); 532 col += 3; 533 if (i < datalen - 1) { 534 if (col + 3 > screenwidth) { 535 printf("\n\t"); 536 col = 8; 537 } else 538 putchar(' '); 539 } 540 } 541 putchar('\n'); 542 return; 543 } 544 if (iohex == 2) { 545 bpl = (screenwidth - 13)/4; 546 if (bpl <= 0) 547 bpl = 1; 548 for (i = 0; i < datalen; i += bpl) { 549 printf(" %04x: ", i); 550 for (j = 0; j < bpl; j++) { 551 if (i+j >= datalen) 552 printf(" "); 553 else 554 printf("%02x ", dp[i+j]); 555 } 556 putchar(' '); 557 for (j = 0; j < bpl; j++) { 558 if (i+j >= datalen) 559 break; 560 c = dp[i+j]; 561 if (!isprint(c)) 562 c = '.'; 563 putchar(c); 564 } 565 putchar('\n'); 566 } 567 return; 568 } 569 (void)printf(" \""); 570 col = 8; 571 for (; datalen > 0; datalen--, dp++) { 572 (void)vis(visbuf, *dp, VIS_CSTYLE, *(dp+1)); 573 cp = visbuf; 574 575 /* 576 * Keep track of printables and 577 * space chars (like fold(1)). 578 */ 579 if (col == 0) { 580 (void)putchar('\t'); 581 col = 8; 582 } 583 switch (*cp) { 584 case '\n': 585 col = 0; 586 (void)putchar('\n'); 587 continue; 588 case '\t': 589 width = 8 - (col&07); 590 break; 591 default: 592 width = strlen(cp); 593 } 594 if (col + width > (screenwidth-2)) { 595 (void)printf("\\\n\t"); 596 col = 8; 597 } 598 col += width; 599 do { 600 (void)putchar(*cp++); 601 } while (*cp); 602 } 603 if (col == 0) 604 (void)printf(" "); 605 (void)printf("\"\n"); 606 } 607 608 static void 609 ktrpsig(struct ktr_psig *psig) 610 { 611 (void)printf("SIG%s ", sys_signame[psig->signo]); 612 if (psig->action == SIG_DFL) 613 (void)printf("SIG_DFL code %d", psig->code); 614 else 615 (void)printf("caught handler=0x%lx mask=0x%x", 616 (u_long)psig->action, psig->mask); 617 switch (psig->signo) { 618 case SIGSEGV: 619 case SIGILL: 620 case SIGBUS: 621 case SIGFPE: 622 printf(" addr=%p trapno=%d", psig->si.si_addr, 623 psig->si.si_trapno); 624 break; 625 default: 626 break; 627 } 628 printf("\n"); 629 } 630 631 static void 632 ktrcsw(struct ktr_csw *cs) 633 { 634 (void)printf("%s %s\n", cs->out ? "stop" : "resume", 635 cs->user ? "user" : "kernel"); 636 } 637 638 static void 639 usage(void) 640 { 641 642 extern char *__progname; 643 fprintf(stderr, "usage: %s " 644 "[-dlnRTXx] [-e emulation] [-f file] [-m maxdata] [-p pid]\n" 645 "%*s[-t [ceinsw]]\n", 646 __progname, sizeof("usage: ") + strlen(__progname), ""); 647 exit(1); 648 } 649 650 static void 651 setemul(const char *name) 652 { 653 int i; 654 655 for (i = 0; emulations[i].name != NULL; i++) 656 if (strcmp(emulations[i].name, name) == 0) { 657 current = &emulations[i]; 658 return; 659 } 660 warnx("Emulation `%s' unknown", name); 661 } 662