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