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