1 /* $NetBSD: kdump.c,v 1.139 2020/04/30 15:12:25 martin 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/cdefs.h> 33 #ifndef lint 34 __COPYRIGHT("@(#) Copyright (c) 1988, 1993\ 35 The Regents of the University of California. All rights reserved."); 36 #endif /* not lint */ 37 38 #ifndef lint 39 #if 0 40 static char sccsid[] = "@(#)kdump.c 8.4 (Berkeley) 4/28/95"; 41 #else 42 __RCSID("$NetBSD: kdump.c,v 1.139 2020/04/30 15:12:25 martin Exp $"); 43 #endif 44 #endif /* not lint */ 45 46 #include <sys/param.h> 47 #include <sys/file.h> 48 #define _KMEMUSER /* To get the pseudo errors defined */ 49 #include <sys/errno.h> 50 #undef _KMEMUSER 51 #include <sys/mman.h> 52 #include <sys/time.h> 53 #include <sys/uio.h> 54 #include <sys/ktrace.h> 55 #include <sys/ioctl.h> 56 #include <sys/ptrace.h> 57 #include <sys/socket.h> 58 #include <sys/futex.h> 59 60 #include <ctype.h> 61 #include <err.h> 62 #include <inttypes.h> 63 #include <signal.h> 64 #include <stddef.h> 65 #include <stdio.h> 66 #include <stdlib.h> 67 #include <string.h> 68 #include <unistd.h> 69 #include <vis.h> 70 #include <util.h> 71 72 #include "ktrace.h" 73 #include "setemul.h" 74 75 #include <sys/syscall.h> 76 77 #define TIMESTAMP_NONE 0x0 78 #define TIMESTAMP_ABSOLUTE 0x1 79 #define TIMESTAMP_ELAPSED 0x2 80 #define TIMESTAMP_RELATIVE 0x4 81 82 static int timestamp, decimal, plain, tail, maxdata = -1, numeric; 83 static int word_size = 0; 84 static pid_t do_pid = -1; 85 static const char *tracefile = NULL; 86 static struct ktr_header ktr_header; 87 static int emul_changed = 0; 88 89 #define eqs(s1, s2) (strcmp((s1), (s2)) == 0) 90 #define small(v) (((long)(v) >= 0) && ((long)(v) < 10)) 91 92 static const char * const ptrace_ops[] = { 93 PT_STRINGS 94 }; 95 96 #ifdef PT_MACHDEP_STRINGS 97 static const char * const ptrace_machdep_ops[] = { PT_MACHDEP_STRINGS }; 98 #endif 99 100 static const char * const linux_ptrace_ops[] = { 101 "PTRACE_TRACEME", 102 "PTRACE_PEEKTEXT", "PTRACE_PEEKDATA", "PTRACE_PEEKUSER", 103 "PTRACE_POKETEXT", "PTRACE_POKEDATA", "PTRACE_POKEUSER", 104 "PTRACE_CONT", "PTRACE_KILL", "PTRACE_SINGLESTEP", 105 NULL, NULL, 106 "PTRACE_GETREGS", "PTRACE_SETREGS", "PTRACE_GETFPREGS", 107 "PTRACE_SETFPREGS", "PTRACE_ATTACH", "PTRACE_DETACH", 108 NULL, NULL, NULL, NULL, NULL, NULL, 109 "PTRACE_SYSCALL", 110 }; 111 112 static const char default_format[] = { "%n\t%E\t%x\n" }; 113 114 static void fmtprint(const char *, const struct ioctlinfo *ii); 115 static int fread_tail(void *, size_t, size_t); 116 static int dumpheader(struct ktr_header *); 117 static int output_ts(const struct timespec *); 118 static void output_long(u_long, int); 119 static void ioctldecode(u_long); 120 static void ktrsyscall(struct ktr_syscall *); 121 static void ktrsysret(struct ktr_sysret *, int); 122 static void ktrnamei(char *, int); 123 static void ktremul(char *, size_t, size_t); 124 static void ktrgenio(struct ktr_genio *, int); 125 static void ktrpsig(void *, int); 126 static void ktrcsw(struct ktr_csw *); 127 static void ktruser(struct ktr_user *, int); 128 static void ktrmib(int *, int); 129 static void ktrexecfd(struct ktr_execfd *); 130 static void usage(void) __dead; 131 static void eprint(int); 132 static void rprint(register_t); 133 static const char *signame(long, int); 134 static void hexdump_buf(const void *, int, int); 135 static void visdump_buf(const void *, int, int); 136 static const struct ioctlinfo *find_ioctl(const char *); 137 138 int 139 main(int argc, char **argv) 140 { 141 unsigned int ktrlen, size; 142 int ch; 143 void *m; 144 int trpoints = 0; 145 int trset = 0; 146 const char *emul_name = "netbsd"; 147 const char *format = default_format; 148 int col; 149 char *cp; 150 151 setprogname(argv[0]); 152 153 if (strcmp(getprogname(), "ioctlprint") == 0) { 154 const struct ioctlinfo *ii; 155 int list = 0; 156 int i; 157 158 while ((ch = getopt(argc, argv, "e:f:l")) != -1) 159 switch (ch) { 160 case 'e': 161 emul_name = optarg; 162 break; 163 case 'f': 164 if (format != default_format) 165 errx(1, "Too many formats"); 166 format = optarg; 167 break; 168 case 'l': 169 list = 1; 170 break; 171 default: 172 usage(); 173 break; 174 } 175 176 setemul(emul_name, 0, 0); 177 argv += optind; 178 argc -= optind; 179 180 if (argc < 1 && !list) 181 usage(); 182 183 if (list) { 184 for (i = 0; ioctlinfo[i].name != NULL; i++) { 185 fmtprint(format, &ioctlinfo[i]); 186 } 187 return 0; 188 } 189 190 for (i = 0; i < argc; i++) { 191 if ((ii = find_ioctl(argv[i])) == NULL) { 192 warnx("Can't find ioctl `%s'", argv[i]); 193 continue; 194 } 195 fmtprint(format, ii); 196 } 197 return 0; 198 } 199 200 timestamp = TIMESTAMP_NONE; 201 202 while ((ch = getopt(argc, argv, "Ee:f:dlm:Nnp:RTt:xX:")) != -1) { 203 switch (ch) { 204 case 'E': 205 timestamp |= TIMESTAMP_ELAPSED; 206 break; 207 case 'e': 208 emul_name = strdup(optarg); /* it's safer to copy it */ 209 break; 210 case 'f': 211 tracefile = optarg; 212 break; 213 case 'd': 214 decimal = 1; 215 break; 216 case 'l': 217 tail = 1; 218 break; 219 case 'p': 220 do_pid = strtoul(optarg, &cp, 0); 221 if (*cp != 0) 222 errx(1,"invalid number %s", optarg); 223 break; 224 case 'm': 225 maxdata = strtoul(optarg, &cp, 0); 226 if (*cp != 0) 227 errx(1,"invalid number %s", optarg); 228 break; 229 case 'N': 230 numeric++; 231 break; 232 case 'n': 233 plain++; 234 break; 235 case 'R': 236 timestamp |= TIMESTAMP_RELATIVE; 237 break; 238 case 'T': 239 timestamp |= TIMESTAMP_ABSOLUTE; 240 break; 241 case 't': 242 trset = 1; 243 trpoints = getpoints(trpoints, optarg); 244 if (trpoints < 0) 245 errx(1, "unknown trace point in %s", optarg); 246 break; 247 case 'x': 248 word_size = 1; 249 break; 250 case 'X': 251 word_size = strtoul(optarg, &cp, 0); 252 if (*cp != 0 || word_size & (word_size - 1) || 253 word_size > 16 || word_size <= 0) 254 errx(1, "argument to -X must be " 255 "1, 2, 4, 8 or 16"); 256 break; 257 default: 258 usage(); 259 } 260 } 261 argv += optind; 262 argc -= optind; 263 264 if (!trset) 265 trpoints = ALL_POINTS; 266 267 if (tracefile == NULL) { 268 if (argc == 1) { 269 tracefile = argv[0]; 270 argv++; 271 argc--; 272 } else 273 tracefile = DEF_TRACEFILE; 274 } 275 276 if (argc > 0) 277 usage(); 278 279 setemul(emul_name, 0, 0); 280 281 m = malloc(size = 1024); 282 if (m == NULL) 283 errx(1, "malloc: %s", strerror(ENOMEM)); 284 if (!freopen(tracefile, "r", stdin)) 285 err(1, "%s", tracefile); 286 while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) { 287 if (trpoints & (1 << ktr_header.ktr_type) && 288 (do_pid == -1 || ktr_header.ktr_pid == do_pid)) 289 col = dumpheader(&ktr_header); 290 else 291 col = -1; 292 if ((ktrlen = ktr_header.ktr_len) > INT_MAX) 293 errx(1, "bogus length 0x%x", ktrlen); 294 if (ktrlen > size) { 295 while (ktrlen > size) 296 size *= 2; 297 m = realloc(m, size); 298 if (m == NULL) 299 errx(1, "realloc: %s", strerror(ENOMEM)); 300 } 301 if (ktrlen && fread_tail(m, ktrlen, 1) == 0) 302 errx(1, "data too short"); 303 if (col == -1) 304 continue; 305 306 /* update context to match currently processed record */ 307 ectx_sanify(ktr_header.ktr_pid); 308 309 switch (ktr_header.ktr_type) { 310 case KTR_SYSCALL: 311 ktrsyscall(m); 312 break; 313 case KTR_SYSRET: 314 ktrsysret(m, ktrlen); 315 break; 316 case KTR_NAMEI: 317 ktrnamei(m, ktrlen); 318 break; 319 case KTR_GENIO: 320 ktrgenio(m, ktrlen); 321 break; 322 case KTR_PSIG: 323 ktrpsig(m, ktrlen); 324 break; 325 case KTR_CSW: 326 ktrcsw(m); 327 break; 328 case KTR_EMUL: 329 ktremul(m, ktrlen, size); 330 break; 331 case KTR_USER: 332 ktruser(m, ktrlen); 333 break; 334 case KTR_EXEC_ARG: 335 case KTR_EXEC_ENV: 336 visdump_buf(m, ktrlen, col); 337 break; 338 case KTR_EXEC_FD: 339 ktrexecfd(m); 340 break; 341 case KTR_MIB: 342 ktrmib(m, ktrlen); 343 break; 344 default: 345 putchar('\n'); 346 hexdump_buf(m, ktrlen, word_size ? word_size : 1); 347 } 348 if (tail) 349 (void)fflush(stdout); 350 } 351 return (0); 352 } 353 354 static void 355 fmtprint(const char *fmt, const struct ioctlinfo *ii) 356 { 357 int c; 358 359 360 while ((c = *fmt++) != '\0') { 361 switch (c) { 362 default: 363 putchar(c); 364 continue; 365 case '\\': 366 switch (c = *fmt) { 367 case '\0': 368 continue; 369 case 'n': 370 putchar('\n'); 371 break; 372 case 't': 373 putchar('\t'); 374 break; 375 } 376 break; 377 case '%': 378 switch (c = *fmt) { 379 case '\0': 380 continue; 381 case '%': 382 default: 383 putchar(c); 384 break; 385 case 'E': 386 printf("%s", ii->expr); 387 break; 388 case 'e': 389 ioctldecode(ii->value); 390 break; 391 case 'n': 392 printf("%s", ii->name); 393 break; 394 case 'x': 395 printf("%#lx", ii->value); 396 break; 397 case 'o': 398 printf("%#lo", ii->value); 399 break; 400 case 'd': case 'i': 401 printf("%ld", ii->value); 402 break; 403 } 404 break; 405 } 406 ++fmt; 407 } 408 } 409 410 static int 411 fread_tail(void *buf, size_t num, size_t size) 412 { 413 int i; 414 415 while ((i = fread(buf, size, num, stdin)) == 0 && tail) { 416 (void)sleep(1); 417 clearerr(stdin); 418 } 419 return (i); 420 } 421 422 static int 423 dumpheader(struct ktr_header *kth) 424 { 425 char unknown[64]; 426 const char *type; 427 static struct timespec starttime, prevtime; 428 struct timespec temp; 429 int col; 430 431 if (__predict_false(kth->ktr_version != KTRFAC_VERSION(KTRFACv2))) 432 errx(EXIT_FAILURE, "Unsupported ktrace version %x", 433 kth->ktr_version); 434 435 switch (kth->ktr_type) { 436 case KTR_SYSCALL: 437 type = "CALL"; 438 break; 439 case KTR_SYSRET: 440 type = "RET "; 441 break; 442 case KTR_NAMEI: 443 type = "NAMI"; 444 break; 445 case KTR_GENIO: 446 type = "GIO "; 447 break; 448 case KTR_PSIG: 449 type = "PSIG"; 450 break; 451 case KTR_CSW: 452 type = "CSW "; 453 break; 454 case KTR_EMUL: 455 type = "EMUL"; 456 break; 457 case KTR_USER: 458 type = "MISC"; 459 break; 460 case KTR_EXEC_ENV: 461 type = "ENV"; 462 break; 463 case KTR_EXEC_ARG: 464 type = "ARG"; 465 break; 466 case KTR_EXEC_FD: 467 type = "FD"; 468 break; 469 case KTR_SAUPCALL: 470 type = "SAU"; 471 break; 472 case KTR_MIB: 473 type = "MIB"; 474 break; 475 default: 476 (void)snprintf(unknown, sizeof(unknown), "UNKNOWN(%d)", 477 kth->ktr_type); 478 type = unknown; 479 } 480 481 col = printf("%6d %6d ", kth->ktr_pid, kth->ktr_lid); 482 col += printf("%-8.*s ", MAXCOMLEN, kth->ktr_comm); 483 if (timestamp) { 484 if (timestamp & TIMESTAMP_ABSOLUTE) { 485 temp.tv_sec = kth->ktr_ts.tv_sec; 486 temp.tv_nsec = kth->ktr_ts.tv_nsec; 487 col += output_ts(&temp); 488 } 489 490 if (timestamp & TIMESTAMP_ELAPSED) { 491 if (starttime.tv_sec == 0) { 492 starttime.tv_sec = kth->ktr_ts.tv_sec; 493 starttime.tv_nsec = kth->ktr_ts.tv_nsec; 494 temp.tv_sec = temp.tv_nsec = 0; 495 } else 496 timespecsub(&kth->ktr_ts, &starttime, &temp); 497 col += output_ts(&temp); 498 } 499 500 if (timestamp & TIMESTAMP_RELATIVE) { 501 if (prevtime.tv_sec == 0) 502 temp.tv_sec = temp.tv_nsec = 0; 503 else 504 timespecsub(&kth->ktr_ts, &prevtime, &temp); 505 prevtime.tv_sec = kth->ktr_ts.tv_sec; 506 prevtime.tv_nsec = kth->ktr_ts.tv_nsec; 507 col += output_ts(&temp); 508 } 509 } 510 col += printf("%-4s ", type); 511 return col; 512 } 513 514 static int 515 output_ts(const struct timespec *ts) 516 { 517 int col; 518 519 if (__predict_true(ts->tv_sec >= 0)) 520 col = printf("%lld.%09ld ", 521 (long long)ts->tv_sec, (long)ts->tv_nsec); 522 else { 523 /* 524 * The time represented by a timespec object ts is always 525 * 526 * ts.tv_sec + ts.tv_nsec * 1e-9 527 * 528 * where ts.tv_sec may be negative but ts.tv_nsec is 529 * always in [0, 1e9). So, for example, -1/4 second is 530 * represented by the struct timespec object 531 * 532 * { .tv_sec = -1, .tv_nsec = 750000000 } 533 */ 534 const struct timespec zero_ts = { 0, 0 }; 535 struct timespec abs_ts; 536 timespecsub(&zero_ts, ts, &abs_ts); 537 col = printf("-%lld.%09ld ", 538 (long long)abs_ts.tv_sec, (long)abs_ts.tv_nsec); 539 } 540 return col; 541 } 542 543 static void 544 output_long(u_long it, int as_x) 545 { 546 if (cur_emul->flags & EMUL_FLAG_NETBSD32) 547 printf(as_x ? "%#x" : "%d", (u_int)it); 548 else 549 printf(as_x ? "%#lx" : "%ld", it); 550 } 551 552 static const char * 553 fcntlname(u_long cmd) 554 { 555 #define FCNTLCASE(a) case a: return # a 556 switch (cmd) { 557 FCNTLCASE(F_DUPFD); 558 FCNTLCASE(F_GETFD); 559 FCNTLCASE(F_SETFD); 560 FCNTLCASE(F_GETFL); 561 FCNTLCASE(F_SETFL); 562 FCNTLCASE(F_GETOWN); 563 FCNTLCASE(F_SETOWN); 564 FCNTLCASE(F_GETLK); 565 FCNTLCASE(F_SETLK); 566 FCNTLCASE(F_SETLKW); 567 FCNTLCASE(F_CLOSEM); 568 FCNTLCASE(F_MAXFD); 569 FCNTLCASE(F_DUPFD_CLOEXEC); 570 FCNTLCASE(F_GETNOSIGPIPE); 571 FCNTLCASE(F_SETNOSIGPIPE); 572 default: 573 return NULL; 574 } 575 } 576 577 static void 578 ioctldecode(u_long cmd) 579 { 580 char dirbuf[4], *dir = dirbuf; 581 int c; 582 583 if (cmd & IOC_IN) 584 *dir++ = 'W'; 585 if (cmd & IOC_OUT) 586 *dir++ = 'R'; 587 *dir = '\0'; 588 589 c = (cmd >> 8) & 0xff; 590 if (isprint(c)) 591 printf("_IO%s('%c',", dirbuf, c); 592 else 593 printf("_IO%s(0x%02x,", dirbuf, c); 594 output_long(cmd & 0xff, decimal == 0); 595 if ((cmd & IOC_VOID) == 0) { 596 putchar(','); 597 output_long(IOCPARM_LEN(cmd), decimal == 0); 598 } 599 putchar(')'); 600 } 601 602 static void 603 putprot(int pr) 604 { 605 const char *s = ""; 606 607 if (pr == PROT_NONE) { 608 fputs("PROT_NONE", stdout); 609 return; 610 } 611 612 if (pr & PROT_READ) { 613 fputs("PROT_READ", stdout); 614 s = "|"; 615 pr &= ~PROT_READ; 616 } 617 618 if (pr & PROT_WRITE) { 619 printf("%sPROT_WRITE", s); 620 pr &= ~PROT_WRITE; 621 s = "|"; 622 } 623 if (pr & PROT_EXEC) { 624 printf("%sPROT_EXEC", s); 625 pr &= ~PROT_EXEC; 626 s = "|"; 627 } 628 if (pr) { 629 printf("%s%#lx", s, (long)pr); 630 } 631 } 632 633 static const char * 634 futex_op_name(u_long op) 635 { 636 #define FUTEXCASE(a) case a: return # a 637 switch (op & FUTEX_CMD_MASK) { 638 FUTEXCASE(FUTEX_WAIT); 639 FUTEXCASE(FUTEX_WAKE); 640 FUTEXCASE(FUTEX_FD); 641 FUTEXCASE(FUTEX_REQUEUE); 642 FUTEXCASE(FUTEX_CMP_REQUEUE); 643 FUTEXCASE(FUTEX_WAKE_OP); 644 FUTEXCASE(FUTEX_LOCK_PI); 645 FUTEXCASE(FUTEX_UNLOCK_PI); 646 FUTEXCASE(FUTEX_TRYLOCK_PI); 647 FUTEXCASE(FUTEX_WAIT_BITSET); 648 FUTEXCASE(FUTEX_WAKE_BITSET); 649 FUTEXCASE(FUTEX_WAIT_REQUEUE_PI); 650 FUTEXCASE(FUTEX_CMP_REQUEUE_PI); 651 default: 652 return NULL; 653 } 654 #undef FUTEXCASE 655 } 656 657 static void 658 futexput(u_long op) 659 { 660 const char *opname = futex_op_name(op); 661 const char *s = ""; 662 663 if (opname == NULL) { 664 printf("%#lx", op & (u_long)FUTEX_CMD_MASK); 665 } else { 666 fputs(opname, stdout); 667 } 668 op &= ~FUTEX_CMD_MASK; 669 670 if (op & FUTEX_PRIVATE_FLAG) { 671 fputs("_PRIVATE", stdout); 672 op &= ~FUTEX_PRIVATE_FLAG; 673 } 674 675 if (op & FUTEX_CLOCK_REALTIME) { 676 printf("%sFUTEX_CLOCK_REALTIME", s); 677 op &= ~FUTEX_CLOCK_REALTIME; 678 s = "|"; 679 } 680 681 if (op) { 682 printf("%s%#lx", s, op); 683 } 684 } 685 686 static void 687 ktrsyscall(struct ktr_syscall *ktr) 688 { 689 int argcount; 690 const struct emulation *emul = cur_emul; 691 register_t *ap; 692 char c; 693 const char *cp; 694 const char *sys_name; 695 696 argcount = ktr->ktr_argsize / sizeof (*ap); 697 698 emul_changed = 0; 699 700 if (numeric || 701 ((ktr->ktr_code >= emul->nsysnames || ktr->ktr_code < 0))) { 702 sys_name = "?"; 703 (void)printf("[%d]", ktr->ktr_code); 704 } else { 705 sys_name = emul->sysnames[ktr->ktr_code]; 706 (void)printf("%s", sys_name); 707 } 708 #define NETBSD32_ "netbsd32_" 709 if (cur_emul->flags & EMUL_FLAG_NETBSD32) { 710 size_t len = strlen(NETBSD32_); 711 if (strncmp(sys_name, NETBSD32_, len) == 0) 712 sys_name += len; 713 } 714 #undef NETBSD32_ 715 716 ap = (register_t *)((char *)ktr + sizeof(struct ktr_syscall)); 717 if (argcount) { 718 c = '('; 719 if (plain) { 720 ; 721 722 } else if (strcmp(sys_name, "exit_group") == 0 || 723 (strcmp(emul->name, "linux") != 0 && 724 strcmp(emul->name, "linux32") != 0 && 725 strcmp(sys_name, "exit") == 0)) { 726 ectx_delete(); 727 728 } else if (strcmp(sys_name, "ioctl") == 0 && argcount >= 2) { 729 (void)putchar('('); 730 output_long((long)*ap, !(decimal || small(*ap))); 731 ap++; 732 argcount--; 733 if ((cp = ioctlname(*ap)) != NULL) 734 (void)printf(",%s", cp); 735 else { 736 (void)putchar(','); 737 ioctldecode(*ap); 738 } 739 ap++; 740 argcount--; 741 c = ','; 742 743 } else if (strcmp(sys_name, "fcntl") == 0 && argcount >= 2) { 744 (void)putchar('('); 745 output_long((long)*ap, !(decimal || small(*ap))); 746 ap++; 747 argcount--; 748 if ((cp = fcntlname(*ap)) != NULL) 749 (void)printf(",%s", cp); 750 else { 751 (void)printf(",%#lx", (unsigned long)*ap); 752 } 753 ap++; 754 argcount--; 755 c = ','; 756 757 /* 758 * Linux name is "futex". 759 * Native name is "__futex". 760 * Both have the same op argument. 761 */ 762 } else if ((strcmp(sys_name, "futex") == 0 || 763 strcmp(sys_name, "__futex") == 0) && 764 argcount > 2) { 765 (void)putchar('('); 766 output_long((long)*ap, 1); 767 (void)putchar(','); 768 ap++; 769 argcount--; 770 futexput(*ap); 771 ap++; 772 argcount--; 773 c = ','; 774 775 } else if ((strstr(sys_name, "sigaction") != NULL || 776 strstr(sys_name, "sigvec") != NULL) && argcount >= 1) { 777 (void)printf("(SIG%s", signame(ap[0], 1)); 778 ap += 1; 779 argcount -= 1; 780 c = ','; 781 782 } else if ((strcmp(sys_name, "kill") == 0 || 783 strcmp(sys_name, "killpg") == 0) && argcount >= 2) { 784 putchar('('); 785 output_long((long)ap[0], !(decimal || small(*ap))); 786 (void)printf(", SIG%s", signame(ap[1], 1)); 787 ap += 2; 788 argcount -= 2; 789 c = ','; 790 } else if (strcmp(sys_name, "mprotect") == 0 && argcount >= 3) { 791 putchar('('); 792 output_long((long)ap[0], !(decimal || small(ap[0]))); 793 c = ','; 794 putchar(c); 795 output_long((long)ap[1], !(decimal || small(ap[1]))); 796 putchar(c); 797 putprot(ap[2]); 798 ap += 3; 799 argcount -= 3; 800 c = ','; 801 } else if (strcmp(sys_name, "mmap") == 0 && argcount >= 6) { 802 char buf[1024]; 803 putchar('('); 804 output_long((long)ap[0], !(decimal || small(ap[0]))); 805 c = ','; 806 putchar(c); 807 output_long((long)ap[1], !(decimal || small(ap[1]))); 808 putchar(c); 809 putprot(ap[2]); 810 snprintb(buf, sizeof(buf), MAP_FMT, ap[3]); 811 printf(",%s", buf); 812 ap += 4; 813 argcount -= 4; 814 c = ','; 815 } else if (strcmp(sys_name, "ptrace") == 0 && argcount >= 1) { 816 putchar('('); 817 if (strcmp(emul->name, "linux") == 0 || 818 strcmp(emul->name, "linux32") == 0) { 819 if ((long)*ap >= 0 && *ap < 820 (register_t)(sizeof(linux_ptrace_ops) / 821 sizeof(linux_ptrace_ops[0]))) 822 (void)printf("%s", 823 linux_ptrace_ops[*ap]); 824 else 825 output_long((long)*ap, 1); 826 } else { 827 if ((long)*ap >= 0 && *ap < (register_t) 828 __arraycount(ptrace_ops)) 829 (void)printf("%s", ptrace_ops[*ap]); 830 #ifdef PT_MACHDEP_STRINGS 831 else if (*ap >= PT_FIRSTMACH && 832 *ap - PT_FIRSTMACH < (register_t) 833 __arraycount(ptrace_machdep_ops)) 834 (void)printf("%s", ptrace_machdep_ops[*ap - PT_FIRSTMACH]); 835 #endif 836 else 837 output_long((long)*ap, 1); 838 } 839 ap++; 840 argcount--; 841 c = ','; 842 843 } 844 while (argcount > 0) { 845 putchar(c); 846 output_long((long)*ap, !(decimal || small(*ap))); 847 ap++; 848 argcount--; 849 c = ','; 850 } 851 (void)putchar(')'); 852 } 853 (void)putchar('\n'); 854 } 855 856 static void 857 ktrsysret(struct ktr_sysret *ktr, int len) 858 { 859 const struct emulation *emul; 860 int error = ktr->ktr_error; 861 int code = ktr->ktr_code; 862 863 if (emul_changed) { 864 /* In order to get system call name right in execve return */ 865 emul = prev_emul; 866 emul_changed = 0; 867 } else 868 emul = cur_emul; 869 870 if (numeric || ((code >= emul->nsysnames || code < 0 || plain > 1))) 871 (void)printf("[%d] ", code); 872 else 873 (void)printf("%s ", emul->sysnames[code]); 874 875 switch (error) { 876 case 0: 877 rprint(ktr->ktr_retval); 878 if (len > (int)offsetof(struct ktr_sysret, ktr_retval_1) && 879 ktr->ktr_retval_1 != 0) { 880 (void)printf(", "); 881 rprint(ktr->ktr_retval_1); 882 } 883 break; 884 885 default: 886 eprint(error); 887 break; 888 } 889 (void)putchar('\n'); 890 } 891 892 static void 893 ktrexecfd(struct ktr_execfd *ktr) 894 { 895 static const char *dnames[] = { DTYPE_NAMES }; 896 if (ktr->ktr_dtype < __arraycount(dnames)) 897 printf("%s %d\n", dnames[ktr->ktr_dtype], ktr->ktr_fd); 898 else 899 printf("UNKNOWN(%u) %d\n", ktr->ktr_dtype, ktr->ktr_fd); 900 } 901 902 static void 903 rprint(register_t ret) 904 { 905 906 if (!plain) { 907 output_long(ret, 0); 908 if (!small(ret)) { 909 putchar('/'); 910 output_long(ret, 1); 911 } 912 } else { 913 output_long(ret, !(decimal || small(ret))); 914 } 915 } 916 917 /* 918 * We print the original emulation's error numerically, but we 919 * translate it to netbsd to print it symbolically. 920 */ 921 static void 922 eprint(int e) 923 { 924 int i = e; 925 926 if (cur_emul->errnomap) { 927 928 /* No remapping for ERESTART and EJUSTRETURN */ 929 /* Kludge for linux that has negative error numbers */ 930 if (cur_emul->errnomap[2] > 0 && e < 0) 931 goto normal; 932 933 for (i = 0; i < cur_emul->nerrnomap; i++) 934 if (e == cur_emul->errnomap[i]) 935 break; 936 937 if (i == cur_emul->nerrnomap) { 938 printf("-1 unknown errno %d", e); 939 return; 940 } 941 } 942 943 normal: 944 switch (i) { 945 case ERESTART: 946 (void)printf("RESTART"); 947 break; 948 949 case EJUSTRETURN: 950 (void)printf("JUSTRETURN"); 951 break; 952 953 default: 954 (void)printf("-1 errno %d", e); 955 if (!plain) 956 (void)printf(" %s", strerror(i)); 957 } 958 } 959 960 static void 961 ktrnamei(char *cp, int len) 962 { 963 964 (void)printf("\"%.*s\"\n", len, cp); 965 } 966 967 static void 968 ktremul(char *name, size_t len, size_t bufsize) 969 { 970 971 if (len >= bufsize) 972 len = bufsize - 1; 973 974 name[len] = '\0'; 975 setemul(name, ktr_header.ktr_pid, 1); 976 emul_changed = 1; 977 978 (void)printf("\"%s\"\n", name); 979 } 980 981 static void 982 hexdump_buf(const void *vdp, int datalen, int word_sz) 983 { 984 const char hex[] = "0123456789abcdef"; 985 char chars[16], prev[16]; 986 char bytes[16 * 3 + 4]; 987 const unsigned char *dp = vdp; 988 const unsigned char *datalim = dp + datalen; 989 const unsigned char *line_end; 990 int off, l = 0, c; 991 char *cp, *bp; 992 int divmask = word_sz - 1; /* block size in bytes */ 993 int gdelim = 3; /* gap between blocks */ 994 int bsize = 2; /* increment for each byte */ 995 int width; 996 int dupl = 0; 997 #if _BYTE_ORDER == _LITTLE_ENDIAN 998 int bswap = word_sz - 1; 999 #else 1000 #define bswap 0 1001 #endif 1002 1003 switch (word_sz) { 1004 case 2: 1005 gdelim = 2; 1006 break; 1007 case 1: 1008 divmask = 7; 1009 bsize = 3; 1010 gdelim = 1; 1011 break; 1012 default: 1013 break; 1014 } 1015 width = 16 * bsize + (16 / (divmask + 1)) * gdelim; 1016 if (word_sz != 1) 1017 width += 2; 1018 1019 for (off = 0; dp < datalim; off += l) { 1020 memset(bytes, ' ', sizeof bytes); 1021 line_end = dp + 16; 1022 if (line_end >= datalim) { 1023 line_end = datalim; 1024 dupl |= 1; /* need to print */ 1025 } else { 1026 if (dupl == 0 || memcmp(dp, prev, sizeof chars)) 1027 dupl |= 1; 1028 } 1029 1030 if (!(dupl & 1)) { 1031 /* This is a duplicate of the line above, count 'em */ 1032 dupl += 2; 1033 dp = line_end; 1034 continue; 1035 } 1036 1037 if (dupl > 3) { 1038 /* previous line as a duplicate */ 1039 if (dupl == 5) 1040 /* Only one duplicate, print line */ 1041 printf("\t%-5.3x%.*s%.*s\n", 1042 off - l, width, bytes, l, chars); 1043 else 1044 printf("\t%.*s\n", 1045 snprintf(NULL, 0, "%3x", off), "*****"); 1046 } 1047 1048 for (l = 0, bp = bytes, cp = chars; dp < line_end; l++) { 1049 c = *dp++; 1050 prev[l] = c; 1051 if ((l & divmask) == 0) 1052 bp += gdelim; 1053 bp[(l ^ bswap) * bsize] = hex[c >> 4]; 1054 bp[(l ^ bswap) * bsize + 1] = hex[c & 0xf]; 1055 *cp++ = isgraph(c) ? c : '.'; 1056 } 1057 1058 printf("\t%-5.3x%.*s%.*s\n", off, width, bytes, l, chars); 1059 dupl = 2; 1060 } 1061 } 1062 1063 static void 1064 visdump_buf(const void *vdp, int datalen, int col) 1065 { 1066 const unsigned char *dp = vdp; 1067 char *cp; 1068 int width; 1069 char visbuf[5]; 1070 static int screenwidth = 0; 1071 1072 if (screenwidth == 0) { 1073 struct winsize ws; 1074 1075 if (!plain && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 && 1076 ws.ws_col > 8) 1077 screenwidth = ws.ws_col; 1078 else 1079 screenwidth = 80; 1080 } 1081 1082 (void)printf("\""); 1083 col++; 1084 for (; datalen > 0; datalen--, dp++) { 1085 (void)svis(visbuf, *dp, VIS_CSTYLE, 1086 datalen > 1 ? *(dp + 1) : 0, "\"\n"); 1087 cp = visbuf; 1088 /* 1089 * Keep track of printables and 1090 * space chars (like fold(1)). 1091 */ 1092 if (col == 0) { 1093 (void)putchar('\t'); 1094 col = 8; 1095 } 1096 switch (*cp) { 1097 case '\n': 1098 col = 0; 1099 (void)putchar('\n'); 1100 continue; 1101 case '\t': 1102 width = 8 - (col & 07); 1103 break; 1104 default: 1105 width = strlen(cp); 1106 } 1107 if (col + width > (screenwidth - 2)) { 1108 (void)printf("\\\n\t"); 1109 col = 8; 1110 if (*cp == '\t') 1111 width = 8; 1112 } 1113 col += width; 1114 do { 1115 (void)putchar(*cp++); 1116 } while (*cp); 1117 } 1118 if (col == 0) 1119 (void)printf(" "); 1120 (void)printf("\"\n"); 1121 } 1122 1123 static void 1124 ktrgenio(struct ktr_genio *ktr, int len) 1125 { 1126 int datalen = len - sizeof (struct ktr_genio); 1127 char *dp = (char *)ktr + sizeof (struct ktr_genio); 1128 1129 if (ktr->ktr_fd != -1) 1130 printf("fd %d ", ktr->ktr_fd); 1131 printf("%s %d bytes\n", 1132 ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen); 1133 if (maxdata == 0) 1134 return; 1135 if (maxdata > 0 && datalen > maxdata) 1136 datalen = maxdata; 1137 if (word_size) { 1138 hexdump_buf(dp, datalen, word_size); 1139 return; 1140 } 1141 (void)printf(" "); 1142 visdump_buf(dp, datalen, 7); 1143 } 1144 1145 static void 1146 ktrpsig(void *v, int len) 1147 { 1148 int signo, first; 1149 struct { 1150 struct ktr_psig ps; 1151 siginfo_t si; 1152 } *psig = v; 1153 siginfo_t *si = &psig->si; 1154 const char *code; 1155 1156 (void)printf("SIG%s ", signame(psig->ps.signo, 0)); 1157 if (psig->ps.action == SIG_DFL) 1158 (void)printf("SIG_DFL"); 1159 else { 1160 (void)printf("caught handler=%p mask=(", psig->ps.action); 1161 first = 1; 1162 for (signo = 1; signo < NSIG; signo++) { 1163 if (sigismember(&psig->ps.mask, signo)) { 1164 if (first) 1165 first = 0; 1166 else 1167 (void)printf(","); 1168 (void)printf("%d", signo); 1169 } 1170 } 1171 (void)printf(")"); 1172 } 1173 switch (len) { 1174 case sizeof(struct ktr_psig): 1175 if (psig->ps.code) 1176 printf(" code=0x%x", psig->ps.code); 1177 printf(psig->ps.action == SIG_DFL ? "\n" : ")\n"); 1178 return; 1179 case sizeof(*psig): 1180 if (si->si_code == 0) { 1181 printf(": code=SI_USER sent by pid=%d, uid=%d)\n", 1182 si->si_pid, si->si_uid); 1183 return; 1184 } 1185 1186 if (si->si_code < 0) { 1187 switch (si->si_code) { 1188 case SI_TIMER: 1189 case SI_QUEUE: 1190 printf(": code=%s sent by pid=%d, uid=%d with " 1191 "sigval %p)\n", si->si_code == SI_TIMER ? 1192 "SI_TIMER" : "SI_QUEUE", si->si_pid, 1193 si->si_uid, si->si_value.sival_ptr); 1194 return; 1195 case SI_ASYNCIO: 1196 case SI_MESGQ: 1197 printf(": code=%s with sigval %p)\n", 1198 si->si_code == SI_ASYNCIO ? 1199 "SI_ASYNCIO" : "SI_MESGQ", 1200 si->si_value.sival_ptr); 1201 return; 1202 case SI_LWP: 1203 printf(": code=SI_LWP sent by pid=%d, " 1204 "uid=%d)\n", si->si_pid, si->si_uid); 1205 return; 1206 default: 1207 code = NULL; 1208 break; 1209 } 1210 if (code) 1211 printf(": code=%s unimplemented)\n", code); 1212 else 1213 printf(": code=%d unimplemented)\n", 1214 si->si_code); 1215 return; 1216 } 1217 1218 if (si->si_code == SI_NOINFO) { 1219 printf(": code=SI_NOINFO\n"); 1220 return; 1221 } 1222 1223 code = siginfocodename(si->si_signo, si->si_code); 1224 switch (si->si_signo) { 1225 case SIGCHLD: 1226 printf(": code=%s child pid=%d, uid=%d, " 1227 " status=%u, utime=%lu, stime=%lu)\n", 1228 code, si->si_pid, 1229 si->si_uid, si->si_status, 1230 (unsigned long) si->si_utime, 1231 (unsigned long) si->si_stime); 1232 return; 1233 case SIGILL: 1234 case SIGFPE: 1235 case SIGSEGV: 1236 case SIGBUS: 1237 case SIGTRAP: 1238 printf(": code=%s, addr=%p, trap=%d)\n", 1239 code, si->si_addr, si->si_trap); 1240 return; 1241 case SIGIO: 1242 printf(": code=%s, fd=%d, band=%lx)\n", 1243 code, si->si_fd, si->si_band); 1244 return; 1245 default: 1246 printf(": code=%s, errno=%d)\n", 1247 code, si->si_errno); 1248 return; 1249 } 1250 /*NOTREACHED*/ 1251 default: 1252 warnx("Unhandled size %d for ktrpsig", len); 1253 break; 1254 } 1255 } 1256 1257 static void 1258 ktrcsw(struct ktr_csw *cs) 1259 { 1260 1261 (void)printf("%s %s\n", cs->out ? "stop" : "resume", 1262 cs->user ? "user" : "kernel"); 1263 } 1264 1265 static void 1266 ktruser_msghdr(const char *name, const void *buf, size_t len) 1267 { 1268 struct msghdr m; 1269 1270 if (len != sizeof(m)) 1271 warnx("%.*s: len %zu != %zu", KTR_USER_MAXIDLEN, name, len, 1272 sizeof(m)); 1273 memcpy(&m, buf, len); 1274 printf("%.*s: [name=%p, namelen=%zu, iov=%p, iovlen=%zu, control=%p, " 1275 "controllen=%zu, flags=%x]\n", KTR_USER_MAXIDLEN, name, 1276 m.msg_name, (size_t)m.msg_namelen, m.msg_iov, (size_t)m.msg_iovlen, 1277 m.msg_control, (size_t)m.msg_controllen, m.msg_flags); 1278 } 1279 1280 static void 1281 ktruser_soname(const char *name, const void *buf, size_t len) 1282 { 1283 char fmt[512]; 1284 sockaddr_snprintf(fmt, sizeof(fmt), "%a", buf); 1285 printf("%.*s: [%s]\n", KTR_USER_MAXIDLEN, name, fmt); 1286 } 1287 1288 static void 1289 ktruser_xattr_name(const char *name, const void *buf, size_t len) 1290 { 1291 printf("%.*s: [%*s]\n", KTR_USER_MAXIDLEN, name, (int)len, 1292 (const char *)buf); 1293 } 1294 1295 static void 1296 ktruser_xattr_val(const char *name, const void *buf, size_t len) 1297 { 1298 const uint8_t *p = buf; 1299 printf("%.*s: ", KTR_USER_MAXIDLEN, name); 1300 for (size_t i = 0; i < len; i++) 1301 printf("%.2x", *p++); 1302 printf("\n"); 1303 } 1304 1305 static void 1306 ktruser_xattr_list(const char *name, const void *buf, size_t len) 1307 { 1308 const uint8_t *p = buf, *ep = p + len; 1309 printf("%.*s:", KTR_USER_MAXIDLEN, name); 1310 while (p < ep) { 1311 int l = *p++; 1312 printf(" %.*s", l, p); 1313 p += l; 1314 } 1315 printf("\n"); 1316 } 1317 1318 static void 1319 ktruser_control(const char *name, const void *buf, size_t len) 1320 { 1321 struct cmsghdr m; 1322 1323 if (len < sizeof(m)) 1324 warnx("%.*s: len %zu < %zu", KTR_USER_MAXIDLEN, name, len, 1325 sizeof(m)); 1326 memcpy(&m, buf, sizeof(m)); 1327 printf("%.*s: [len=%zu, level=%d, type=%d]\n", KTR_USER_MAXIDLEN, name, 1328 (size_t)m.cmsg_len, m.cmsg_level, m.cmsg_type); 1329 } 1330 1331 static void 1332 ktruser_malloc(const char *name, const void *buf, size_t len) 1333 { 1334 struct ut { void *p; size_t s; void *r; } m; 1335 1336 if (len != sizeof(m)) 1337 warnx("%.*s: len %zu != %zu", KTR_USER_MAXIDLEN, name, len, 1338 sizeof(m)); 1339 memcpy(&m, buf, len < sizeof(m) ? len : sizeof(m)); 1340 if (m.p == NULL && m.s == 0 && m.r == NULL) 1341 printf("%.*s: malloc_init()\n", KTR_USER_MAXIDLEN, name); 1342 else if (m.p != NULL && m.s != 0) 1343 printf("%.*s: %p = realloc(%p, %zu)\n", KTR_USER_MAXIDLEN, name, 1344 m.r, m.p, m.s); 1345 else if (m.s == 0) 1346 printf("%.*s: free(%p)\n", KTR_USER_MAXIDLEN, name, m.p); 1347 else 1348 printf("%.*s: %p = malloc(%zu)\n", KTR_USER_MAXIDLEN, name, 1349 m.r, m.s); 1350 } 1351 1352 static void 1353 ktruser_misc(const char *name, const void *buf, size_t len) 1354 { 1355 size_t i; 1356 const char *dta = buf; 1357 1358 printf("%.*s: %zu, ", KTR_USER_MAXIDLEN, name, len); 1359 for (i = 0; i < len; i++) 1360 printf("%02x", (unsigned char)dta[i]); 1361 printf("\n"); 1362 } 1363 1364 static struct { 1365 const char *name; 1366 void (*func)(const char *, const void *, size_t); 1367 } nv[] = { 1368 { "msghdr", ktruser_msghdr }, 1369 { "mbsoname", ktruser_soname }, 1370 { "mbcontrol", ktruser_control }, 1371 { "malloc", ktruser_malloc }, 1372 { "xattr-name", ktruser_xattr_name }, 1373 { "xattr-val", ktruser_xattr_val }, 1374 { "xattr-list", ktruser_xattr_list }, 1375 { NULL, ktruser_misc }, 1376 }; 1377 1378 static void 1379 ktruser(struct ktr_user *usr, int len) 1380 { 1381 unsigned char *dta; 1382 1383 len -= sizeof(struct ktr_user); 1384 dta = (unsigned char *)(usr + 1); 1385 if (word_size) { 1386 printf("%.*s:", KTR_USER_MAXIDLEN, usr->ktr_id); 1387 printf("\n"); 1388 hexdump_buf(dta, len, word_size); 1389 return; 1390 } 1391 for (size_t j = 0; j < __arraycount(nv); j++) 1392 if (nv[j].name == NULL || 1393 strncmp(nv[j].name, usr->ktr_id, KTR_USER_MAXIDLEN) == 0) { 1394 (*nv[j].func)(usr->ktr_id, dta, len); 1395 break; 1396 } 1397 } 1398 1399 static void 1400 ktrmib(int *namep, int len) 1401 { 1402 size_t i; 1403 1404 for (i = 0; i < (len / sizeof(*namep)); i++) 1405 printf("%s%d", (i == 0) ? "" : ".", namep[i]); 1406 printf("\n"); 1407 } 1408 1409 static const char * 1410 signame(long sig, int xlat) 1411 { 1412 static char buf[64]; 1413 1414 if (sig == 0) 1415 return " 0"; 1416 else if (sig < 0 || sig >= NSIG) { 1417 (void)snprintf(buf, sizeof(buf), "*unknown %ld*", sig); 1418 return buf; 1419 } else 1420 return sys_signame[(xlat && cur_emul->signalmap != NULL) ? 1421 cur_emul->signalmap[sig] : sig]; 1422 } 1423 1424 static void 1425 usage(void) 1426 { 1427 if (strcmp(getprogname(), "ioctlprint") == 0) { 1428 (void)fprintf(stderr, "Usage: %s [-l] [-e emulation] [-f format] <ioctl> ...\n", 1429 getprogname()); 1430 } else { 1431 (void)fprintf(stderr, "Usage: %s [-dElNnRT] [-e emulation] " 1432 "[-f file] [-m maxdata] [-p pid]\n [-t trstr] " 1433 "[-x | -X size] [file]\n", getprogname()); 1434 } 1435 exit(1); 1436 } 1437 1438 static const struct ioctlinfo * 1439 find_ioctl_by_name(const char *name) 1440 { 1441 for (size_t i = 0; ioctlinfo[i].name != NULL; i++) { 1442 if (strcmp(name, ioctlinfo[i].name) == 0) 1443 return &ioctlinfo[i]; 1444 } 1445 return NULL; 1446 } 1447 1448 static const struct ioctlinfo * 1449 find_ioctl_by_value(unsigned long value) 1450 { 1451 for (size_t i = 0; ioctlinfo[i].name != NULL; i++) { 1452 if (value == ioctlinfo[i].value) 1453 return &ioctlinfo[i]; 1454 } 1455 return NULL; 1456 } 1457 1458 static const struct ioctlinfo * 1459 find_ioctl(const char *name) 1460 { 1461 if (isalpha((unsigned char)*name)) { 1462 return find_ioctl_by_name(name); 1463 } 1464 int e; 1465 unsigned long u = strtou(name, NULL, 0, 0, ULONG_MAX, &e); 1466 if (e) 1467 errc(1, e, "invalid argument: `%s'", name); 1468 return find_ioctl_by_value(u); 1469 } 1470