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