1 /* $NetBSD: dump.c,v 1.48 2021/05/01 18:07:52 rillig 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 #endif 42 __RCSID("$NetBSD: dump.c,v 1.48 2021/05/01 18:07:52 rillig Exp $"); 43 #endif /* not lint */ 44 45 #include <sys/param.h> 46 #define _KERNEL 47 #include <sys/errno.h> 48 #undef _KERNEL 49 #include <sys/ioctl.h> 50 #include <sys/time.h> 51 #include <sys/uio.h> 52 #include <sys/ktrace.h> 53 #include <sys/ptrace.h> 54 #include <sys/queue.h> 55 56 #include <err.h> 57 #include <signal.h> 58 #include <stdarg.h> 59 #include <stddef.h> 60 #include <stdio.h> 61 #include <stdlib.h> 62 #include <string.h> 63 #include <unistd.h> 64 #include <vis.h> 65 66 #include "ktrace.h" 67 #include "misc.h" 68 #include "setemul.h" 69 70 int timestamp, decimal, fancy = 1, tail, maxdata; 71 72 int width; /* Keep track of current columns. */ 73 74 #include <sys/syscall.h> 75 76 static const char *const ptrace_ops[] = { 77 PT_STRINGS 78 }; 79 80 #ifdef PT_MACHDEP_STRINGS 81 static const char * const ptrace_machdep_ops[] = { PT_MACHDEP_STRINGS }; 82 #endif 83 84 struct ktr_entry { 85 TAILQ_ENTRY(ktr_entry) kte_list; 86 struct ktr_header kte_kth; 87 }; 88 89 TAILQ_HEAD(kteq, ktr_entry) ktependq = TAILQ_HEAD_INITIALIZER(ktependq); 90 91 void argprint(const char *, register_t **, int *); 92 void dumpheader(struct ktr_header *); 93 int dumprecord(int, FILE *); 94 void flushpendq(struct ktr_entry *); 95 int fread_tail(void *, int, int, FILE *); 96 void genioprint(struct ktr_header *); 97 struct ktr_entry * 98 getpendq(struct ktr_header *, int, struct kteq *); 99 struct ktr_entry * 100 getrecord(FILE *); 101 void indent(int); 102 void ioctldecode(u_long); 103 void ktrcsw(struct ktr_entry *); 104 void ktremul(struct ktr_entry *); 105 void ktrgenio(struct ktr_entry *); 106 void ktrnamei(struct ktr_entry *); 107 void ktrpsig(struct ktr_entry *); 108 void ktrsyscall(struct ktr_entry *); 109 void ktrsysret(struct ktr_entry *); 110 void nameiargprint(const char *, struct ktr_header *, register_t **, int *); 111 void nameiprint(struct ktr_header *); 112 void newline(void); 113 void putpendq(struct ktr_entry *); 114 void syscallnameprint(int); 115 void syscallprint(struct ktr_header *); 116 void sysretprint(struct ktr_header *); 117 int xwprintf(const char *, ...) __printflike(1, 2); 118 void *xrealloc(void *, size_t *, size_t); 119 120 int 121 xwprintf(const char *fmt, ...) 122 { 123 va_list ap; 124 int w; 125 126 va_start(ap, fmt); 127 w = vprintf(fmt, ap); 128 if (w == -1) 129 warn("vprintf"); 130 else 131 width += w; 132 va_end(ap); 133 return (w); 134 } 135 136 void 137 newline(void) 138 { 139 140 if (width > 0) { 141 printf("\n"); 142 width = 0; 143 } 144 } 145 146 void 147 indent(int col) 148 { 149 150 while (width < col) 151 if (xwprintf(" ") < 0) 152 break; 153 } 154 155 void * 156 xrealloc(void *p, size_t *siz, size_t req) 157 { 158 159 if (*siz < req) { 160 if (*siz == 0) 161 *siz = 1; 162 while (*siz < req) 163 *siz <<= 1; 164 p = realloc(p, *siz); 165 if (p == NULL) 166 err(EXIT_FAILURE, "realloc: %lu bytes", 167 (u_long)*siz); 168 } 169 return (p); 170 } 171 172 struct ktr_entry * 173 getrecord(FILE *fp) 174 { 175 struct ktr_entry *kte; 176 struct ktr_header *kth; 177 char *cp; 178 size_t siz, len; 179 180 siz = 0; 181 kte = xrealloc(NULL, &siz, sizeof(struct ktr_entry)); 182 kth = &kte->kte_kth; 183 if (fread_tail(kth, sizeof(struct ktr_header), 1, fp) == 0) { 184 free(kte); 185 return (NULL); 186 } 187 188 if (kth->ktr_len < 0) 189 errx(EXIT_FAILURE, "bogus length 0x%x", kth->ktr_len); 190 len = kth->ktr_len; 191 if (len > 0) { 192 /* + 1 to ensure room for NUL terminate */ 193 kte = xrealloc(kte, &siz, sizeof(struct ktr_entry) + len + 1); 194 if (fread_tail(cp = (char *)(&kte->kte_kth + 1), 195 len, 1, fp) == 0) 196 errx(EXIT_FAILURE, "data too short"); 197 cp[len] = 0; 198 } 199 200 return (kte); 201 } 202 203 #define KTE_TYPE(kte) ((kte)->kte_kth.ktr_type) 204 #define KTE_PID(kte) ((kte)->kte_kth.ktr_pid) 205 #define KTE_LID(kte) ((kte)->kte_kth.ktr_lid) 206 #define KTE_MATCH(kte, type, pid, lid) \ 207 (KTE_TYPE(kte) == (type) && KTE_PID(kte) == (pid) && \ 208 KTE_LID(kte) == (lid)) 209 210 void 211 putpendq(struct ktr_entry *kte) 212 { 213 214 TAILQ_INSERT_TAIL(&ktependq, kte, kte_list); 215 } 216 217 void 218 flushpendq(struct ktr_entry *us) 219 { 220 struct ktr_entry *kte, *kte_next; 221 int pid = KTE_PID(us), lid = KTE_LID(us); 222 223 for (kte = TAILQ_FIRST(&ktependq); kte != NULL; kte = kte_next) { 224 kte_next = TAILQ_NEXT(kte, kte_list); 225 if (KTE_PID(kte) == pid || KTE_LID(kte) == lid) { 226 TAILQ_REMOVE(&ktependq, kte, kte_list); 227 free(kte); 228 } 229 } 230 } 231 232 struct ktr_entry * 233 getpendq(struct ktr_header *us, int type, struct kteq *kteq) 234 { 235 struct ktr_entry *kte, *kte_next; 236 int pid = us->ktr_pid, lid = us->ktr_lid; 237 238 if (kteq != NULL) 239 TAILQ_INIT(kteq); 240 for (kte = TAILQ_FIRST(&ktependq); kte != NULL; kte = kte_next) { 241 kte_next = TAILQ_NEXT(kte, kte_list); 242 if (KTE_MATCH(kte, type, pid, lid)) { 243 TAILQ_REMOVE(&ktependq, kte, kte_list); 244 if (kteq != NULL) 245 TAILQ_INSERT_TAIL(kteq, kte, kte_list); 246 else 247 break; 248 } 249 } 250 251 return (kteq ? TAILQ_FIRST(kteq) : kte); 252 } 253 254 int 255 dumprecord(int trpoints, FILE *fp) 256 { 257 struct ktr_entry *kte; 258 struct ktr_header *kth; 259 260 kte = getrecord(fp); 261 if (kte == NULL) 262 return (0); 263 264 kth = &kte->kte_kth; 265 if ((trpoints & (1 << kth->ktr_type)) == 0) { 266 free(kte); 267 goto out; 268 } 269 270 /* Update context to match currently processed record. */ 271 ectx_sanify(kth->ktr_pid); 272 273 switch (kth->ktr_type) { 274 case KTR_SYSCALL: 275 ktrsyscall(kte); 276 break; 277 case KTR_SYSRET: 278 ktrsysret(kte); 279 break; 280 case KTR_NAMEI: 281 putpendq(kte); 282 break; 283 case KTR_GENIO: 284 putpendq(kte); 285 break; 286 case KTR_PSIG: 287 ktrpsig(kte); 288 break; 289 case KTR_CSW: 290 ktrcsw(kte); 291 break; 292 case KTR_EMUL: 293 putpendq(kte); 294 break; 295 default: 296 /* 297 * XXX: Other types added recently. 298 */ 299 free(kte); 300 break; 301 } 302 newline(); 303 304 out: 305 return (1); 306 } 307 308 void 309 dumpfile(const char *file, int fd, int trpoints) 310 { 311 FILE *fp; 312 313 if (file == NULL || *file == 0) { 314 if ((fp = fdopen(fd, "r")) == NULL) 315 err(EXIT_FAILURE, "fdopen(%d)", fd); 316 } else if (strcmp(file, "-") == 0) 317 fp = stdin; 318 else if ((fp = fopen(file, "r")) == NULL) 319 err(EXIT_FAILURE, "fopen: %s", file); 320 321 for (width = 0; dumprecord(trpoints, fp) != 0;) 322 if (tail) 323 (void)fflush(stdout); 324 325 newline(); 326 327 /* 328 * XXX: Dump pending KTR_SYSCALL if any? 329 */ 330 } 331 332 int 333 fread_tail(void *buf, int size, int num, FILE *fp) 334 { 335 int i; 336 337 while ((i = fread(buf, size, num, fp)) == 0 && tail) { 338 (void)sleep(1); 339 clearerr(fp); 340 } 341 return (i); 342 } 343 344 void 345 dumpheader(struct ktr_header *kth) 346 { 347 union timeholder { 348 struct timeval tv; 349 struct timespec ts; 350 }; 351 static union timeholder prevtime; 352 union timeholder temp; 353 354 temp.tv.tv_sec = temp.tv.tv_usec = 0; 355 xwprintf("%6d ", kth->ktr_pid); 356 if (kth->ktr_version > KTRFAC_VERSION(KTRFACv0)) 357 xwprintf("%6d ", kth->ktr_lid); 358 xwprintf("%-8.*s ", MAXCOMLEN, kth->ktr_comm); 359 if (timestamp) { 360 if (timestamp == 2) { 361 switch (kth->ktr_version) { 362 case KTRFAC_VERSION(KTRFACv0): 363 if (prevtime.tv.tv_sec == 0) 364 temp.tv.tv_sec = temp.tv.tv_usec = 0; 365 else 366 timersub(&kth->ktr_otv, 367 &prevtime.tv, &temp.tv); 368 prevtime.tv.tv_sec = kth->ktr_otv.tv_sec; 369 prevtime.tv.tv_usec = kth->ktr_otv.tv_usec; 370 break; 371 372 case KTRFAC_VERSION(KTRFACv1): 373 if (prevtime.ts.tv_sec == 0) 374 temp.ts.tv_sec = temp.ts.tv_nsec = 0; 375 else 376 timespecsub(&kth->ktr_time, 377 &prevtime.ts, &temp.ts); 378 prevtime.ts.tv_sec = kth->ktr_ots.tv_sec; 379 prevtime.ts.tv_nsec = kth->ktr_ots.tv_nsec; 380 break; 381 382 case KTRFAC_VERSION(KTRFACv2): 383 if (prevtime.ts.tv_sec == 0) 384 temp.ts.tv_sec = temp.ts.tv_nsec = 0; 385 else 386 timespecsub(&kth->ktr_time, 387 &prevtime.ts, &temp.ts); 388 prevtime.ts.tv_sec = kth->ktr_ts.tv_sec; 389 prevtime.ts.tv_nsec = kth->ktr_ts.tv_nsec; 390 break; 391 } 392 } else { 393 switch (kth->ktr_version) { 394 case KTRFAC_VERSION(KTRFACv0): 395 temp.tv.tv_sec = kth->ktr_otv.tv_sec; 396 temp.tv.tv_usec = kth->ktr_otv.tv_usec; 397 break; 398 case KTRFAC_VERSION(KTRFACv1): 399 temp.ts.tv_sec = kth->ktr_ots.tv_sec; 400 temp.ts.tv_nsec = kth->ktr_ots.tv_nsec; 401 break; 402 case KTRFAC_VERSION(KTRFACv2): 403 temp.ts.tv_sec = kth->ktr_ts.tv_sec; 404 temp.ts.tv_nsec = kth->ktr_ts.tv_nsec; 405 break; 406 } 407 } 408 if (kth->ktr_version == KTRFAC_VERSION(KTRFACv0)) 409 xwprintf("%lld.%06ld ", 410 (long long)temp.tv.tv_sec, (long)temp.tv.tv_usec); 411 else 412 xwprintf("%lld.%09ld ", 413 (long long)temp.ts.tv_sec, (long)temp.ts.tv_nsec); 414 } 415 } 416 417 void 418 ioctldecode(u_long cmd) 419 { 420 char dirbuf[4], *dir = dirbuf; 421 422 if (cmd & IOC_OUT) 423 *dir++ = 'W'; 424 if (cmd & IOC_IN) 425 *dir++ = 'R'; 426 *dir = '\0'; 427 428 xwprintf(decimal ? ", _IO%s('%c',%ld" : ", _IO%s('%c',%#lx", 429 dirbuf, (int) ((cmd >> 8) & 0xff), cmd & 0xff); 430 if ((cmd & IOC_VOID) == 0) 431 xwprintf(decimal ? ",%ld)" : ",%#lx)", 432 (cmd >> 16) & 0xff); 433 else 434 xwprintf(")"); 435 } 436 437 void 438 nameiargprint(const char *prefix, struct ktr_header *kth, 439 register_t **ap, int *argsize) 440 { 441 struct ktr_entry *kte; 442 443 if (*argsize == 0) 444 errx(EXIT_FAILURE, "argument expected"); 445 /* 446 * XXX: binary emulation mode. 447 */ 448 kte = getpendq(kth, KTR_NAMEI, NULL); 449 if (kte == NULL) 450 argprint(prefix, ap, argsize); 451 else { 452 xwprintf("%s", prefix); 453 nameiprint(&kte->kte_kth); 454 free(kte); 455 (*ap)++; 456 *argsize -= sizeof(register_t); 457 } 458 } 459 460 void 461 syscallnameprint(int code) 462 { 463 464 if (code >= cur_emul->nsysnames || code < 0) 465 xwprintf("[%d]", code); 466 else 467 xwprintf("%s", cur_emul->sysnames[code]); 468 } 469 470 void 471 argprint(const char *prefix, register_t **ap, int *argsize) 472 { 473 474 if (decimal) 475 xwprintf("%s%ld", prefix, (long)**ap); 476 else 477 xwprintf("%s%#lx", prefix, (long)**ap); 478 (*ap)++; 479 *argsize -= sizeof(register_t); 480 } 481 482 void 483 syscallprint(struct ktr_header *kth) 484 { 485 struct ktr_syscall *ktr = (struct ktr_syscall *)(kth + 1); 486 register_t *ap; 487 const char *s; 488 int argsize; 489 490 syscallnameprint(ktr->ktr_code); 491 492 /* 493 * Arguments processing. 494 */ 495 argsize = ktr->ktr_argsize; 496 if (argsize == 0) { 497 xwprintf("("); 498 goto noargument; 499 } 500 501 ap = (register_t *)(ktr + 1); 502 if (!fancy) 503 goto print_first; 504 505 switch (ktr->ktr_code) { 506 /* 507 * All these have a path as the first param. 508 * The order is same as syscalls.master. 509 */ 510 case SYS_open: 511 case SYS_link: 512 case SYS_unlink: 513 case SYS_chdir: 514 case SYS___mknod50: 515 case SYS_chmod: 516 case SYS_chown: 517 case SYS_unmount: 518 case SYS_access: 519 case SYS_chflags: 520 case SYS_acct: 521 case SYS_revoke: 522 case SYS_symlink: 523 case SYS_readlink: 524 case SYS_execve: 525 case SYS_chroot: 526 case SYS_rename: 527 case SYS_mkfifo: 528 case SYS_mkdir: 529 case SYS_rmdir: 530 case SYS___utimes50: 531 case SYS_compat_50_quotactl: 532 case SYS___quotactl: 533 case SYS___statvfs190: 534 case SYS_compat_30_getfh: 535 case SYS_pathconf: 536 case SYS_truncate: 537 case SYS_undelete: 538 case SYS___posix_rename: 539 case SYS_lchmod: 540 case SYS_lchown: 541 case SYS___lutimes50: 542 case SYS___stat50: 543 case SYS___lstat50: 544 case SYS___posix_chown: 545 case SYS___posix_lchown: 546 case SYS_lchflags: 547 case SYS___getfh30: 548 nameiargprint("(", kth, &ap, &argsize); 549 550 /* 551 * 2nd argument is also pathname. 552 */ 553 switch (ktr->ktr_code) { 554 case SYS_link: 555 case SYS_rename: 556 case SYS___posix_rename: 557 nameiargprint(", ", kth, &ap, &argsize); 558 break; 559 } 560 break; 561 562 case SYS_compat_16___sigaction14 : 563 if ((int)*ap < 0 || (int)*ap >= MAXSIGNALS) 564 xwprintf("(%d", (int)*ap); 565 else 566 xwprintf("(%s", signals[(int)*ap].name); 567 ap++; 568 argsize -= sizeof(register_t); 569 break; 570 571 case SYS_ioctl : 572 argprint("(", &ap, &argsize); 573 if ((s = ioctlname(*ap)) != NULL) 574 xwprintf(", %s", s); 575 else 576 ioctldecode(*ap); 577 ap++; 578 argsize -= sizeof(register_t); 579 break; 580 581 case SYS_ptrace : 582 if ((long)*ap >= 0 && 583 *ap < (register_t)__arraycount(ptrace_ops)) 584 xwprintf("(%s", ptrace_ops[*ap]); 585 #ifdef PT_MACHDEP_STRINGS 586 else if (*ap >= PT_FIRSTMACH && 587 *ap - PT_FIRSTMACH < (register_t) 588 __arraycount(ptrace_machdep_ops)) 589 xwprintf("(%s", ptrace_machdep_ops[*ap - PT_FIRSTMACH]); 590 #endif 591 else 592 xwprintf("(%ld", (long)*ap); 593 ap++; 594 argsize -= sizeof(register_t); 595 break; 596 597 default: 598 print_first: 599 argprint("(", &ap, &argsize); 600 break; 601 } 602 603 /* Print rest of argument. */ 604 while (argsize > 0) 605 argprint(", ", &ap, &argsize); 606 607 noargument: 608 xwprintf(")"); 609 } 610 611 void 612 ktrsyscall(struct ktr_entry *kte) 613 { 614 struct ktr_header *kth = &kte->kte_kth; 615 struct ktr_syscall *ktr = (struct ktr_syscall *)(kth + 1); 616 617 switch (ktr->ktr_code) { 618 case SYS_exit: 619 dumpheader(kth); 620 syscallprint(kth); 621 break; 622 default: 623 putpendq(kte); 624 return; 625 } 626 627 free(kte); 628 } 629 630 void 631 sysretprint(struct ktr_header *kth) 632 { 633 struct ktr_sysret *ktr = (struct ktr_sysret *)(kth + 1); 634 register_t ret = ktr->ktr_retval; 635 int error = ktr->ktr_error; 636 637 indent(50); 638 if (error == EJUSTRETURN) 639 xwprintf(" JUSTRETURN"); 640 else if (error == ERESTART) 641 xwprintf(" RESTART"); 642 else if (error) { 643 xwprintf(" Err#%d", error); 644 if (error < MAXERRNOS && error >= 0) 645 xwprintf(" %s", errnos[error].name); 646 } else 647 switch (ktr->ktr_code) { 648 case SYS_mremap: 649 case SYS_mmap: 650 xwprintf(" = %p", (void *)(intptr_t)ret); 651 break; 652 default: 653 xwprintf(" = %ld", (long)ret); 654 if (kth->ktr_len > (int)offsetof(struct ktr_sysret, 655 ktr_retval_1) && ktr->ktr_retval_1 != 0) 656 xwprintf(", %ld", (long)ktr->ktr_retval_1); 657 break; 658 } 659 } 660 661 void 662 ktrsysret(struct ktr_entry *kte) 663 { 664 struct ktr_header *kth = &kte->kte_kth; 665 struct ktr_sysret *ktr = (struct ktr_sysret *)(kth + 1); 666 struct ktr_entry *emul; 667 struct ktr_entry *genio; 668 struct ktr_entry *syscall_ent; 669 670 dumpheader(kth); 671 672 /* Print syscall name and arguments. */ 673 syscall_ent = getpendq(kth, KTR_SYSCALL, NULL); 674 if (syscall_ent == NULL) { 675 /* 676 * Possibly a child of fork/vfork, or tracing of 677 * process started during system call. 678 */ 679 syscallnameprint(ktr->ktr_code); 680 } else { 681 syscallprint(&syscall_ent->kte_kth); 682 free(syscall_ent); 683 } 684 685 /* Print return value and an error if any. */ 686 sysretprint(kth); 687 688 genio = getpendq(kth, KTR_GENIO, NULL); 689 if (genio != NULL) { 690 genioprint(&genio->kte_kth); 691 free(genio); 692 } 693 694 emul = getpendq(kth, KTR_EMUL, NULL); 695 if (emul != NULL) { 696 newline(); 697 ktremul(emul); 698 } 699 700 flushpendq(kte); 701 free(kte); 702 } 703 704 void 705 nameiprint(struct ktr_header *kth) 706 { 707 708 xwprintf("\"%.*s\"", kth->ktr_len, (char *)(kth + 1)); 709 } 710 711 #ifdef notused 712 void 713 ktrnamei(struct ktr_entry *kte) 714 { 715 struct ktr_header *kth = &kte->kte_kth; 716 717 dumpheader(kth); 718 xwprintf("namei("); 719 nameiprint(kth); 720 xwprintf(")"); 721 722 free(kte); 723 } 724 #endif 725 726 void 727 ktremul(struct ktr_entry *kte) 728 { 729 struct ktr_header *kth = &kte->kte_kth; 730 char *emul = (char *)(kth + 1); 731 732 dumpheader(kth); 733 xwprintf("emul(%s)", emul); 734 setemul(emul, kth->ktr_pid, 1); 735 736 free(kte); 737 } 738 739 void 740 genioprint(struct ktr_header *kth) 741 { 742 struct ktr_genio *ktr = (struct ktr_genio *)(kth + 1); 743 static int screenwidth = 0; 744 int datalen = kth->ktr_len - sizeof(struct ktr_genio); 745 /* 746 * Need to be unsigned type so that positive value is passed 747 * to vis(), which will call isgraph(). 748 */ 749 unsigned char *dp = (unsigned char *)(ktr + 1); 750 int w; 751 char visbuf[5]; 752 753 if (screenwidth == 0) { 754 struct winsize ws; 755 756 if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 && 757 ws.ws_col > 8) 758 screenwidth = ws.ws_col; 759 else 760 screenwidth = 80; 761 } 762 763 if (maxdata && datalen > maxdata) 764 datalen = maxdata; 765 newline(); 766 xwprintf(" \""); 767 for (; datalen > 0; datalen--, dp++) { 768 (void) vis(visbuf, *dp, VIS_NL|VIS_TAB|VIS_CSTYLE, 769 /* We put NUL at the end of buffer when reading */ 770 *(dp + 1)); 771 visbuf[4] = '\0'; 772 w = strlen(visbuf); 773 if (width + w + 2 >= screenwidth) 774 break; 775 xwprintf("%s", visbuf); 776 if (width + 2 >= screenwidth) 777 break; 778 } 779 xwprintf("\""); 780 } 781 782 #ifdef notused 783 void 784 ktrgenio(struct ktr_entry *kte) 785 { 786 struct ktr_header *kth = &kte->kte_kth; 787 struct ktr_genio *ktr = (struct ktr_genio *)(kth + 1); 788 789 dumpheader(kth); 790 xwprintf("genio fd %d %s", 791 ktr->ktr_fd, ktr->ktr_rw ? "write" : "read"); 792 genioprint(kth); 793 794 free(kte); 795 } 796 #endif 797 798 void 799 ktrpsig(struct ktr_entry *kte) 800 { 801 struct ktr_header *kth = &kte->kte_kth; 802 struct ktr_psig *psig = (struct ktr_psig *)(kth + 1); 803 804 dumpheader(kth); 805 xwprintf("SIG%s ", sys_signame[psig->signo]); 806 if (psig->action == SIG_DFL) 807 xwprintf("SIG_DFL"); 808 else { 809 xwprintf("caught handler=0x%lx mask=0x%lx code=0x%x", 810 (u_long)psig->action, (unsigned long)psig->mask.__bits[0], 811 psig->code); 812 } 813 814 free(kte); 815 } 816 817 void 818 ktrcsw(struct ktr_entry *kte) 819 { 820 struct ktr_header *kth = &kte->kte_kth; 821 struct ktr_csw *cs = (struct ktr_csw *)(kth + 1); 822 823 dumpheader(kth); 824 xwprintf("%s %s", cs->out ? "stop" : "resume", 825 cs->user ? "user" : "kernel"); 826 827 free(kte); 828 } 829