1 /* $NetBSD: dump.c,v 1.12 2002/06/06 10:48:49 enami 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. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include <sys/cdefs.h> 37 #ifndef lint 38 __COPYRIGHT("@(#) Copyright (c) 1988, 1993\n\ 39 The Regents of the University of California. All rights reserved.\n"); 40 #endif /* not lint */ 41 42 #ifndef lint 43 #if 0 44 static char sccsid[] = "@(#)kdump.c 8.4 (Berkeley) 4/28/95"; 45 #endif 46 __RCSID("$NetBSD: dump.c,v 1.12 2002/06/06 10:48:49 enami Exp $"); 47 #endif /* not lint */ 48 49 #include <sys/param.h> 50 #define _KERNEL 51 #include <sys/errno.h> 52 #undef _KERNEL 53 #include <sys/time.h> 54 #include <sys/uio.h> 55 #include <sys/ktrace.h> 56 #include <sys/ioctl.h> 57 #include <sys/ptrace.h> 58 #define _KERNEL 59 #include <sys/errno.h> 60 #undef _KERNEL 61 62 #include <err.h> 63 #include <signal.h> 64 #include <stdio.h> 65 #include <stdlib.h> 66 #include <string.h> 67 #include <unistd.h> 68 #include <vis.h> 69 70 #include "ktrace.h" 71 #include "misc.h" 72 #include "setemul.h" 73 74 int timestamp, decimal, fancy = 1, tail, maxdata; 75 76 #define eqs(s1, s2) (strcmp((s1), (s2)) == 0) 77 78 #include <sys/syscall.h> 79 80 static char *ptrace_ops[] = { 81 "PT_TRACE_ME", "PT_READ_I", "PT_READ_D", "PT_READ_U", 82 "PT_WRITE_I", "PT_WRITE_D", "PT_WRITE_U", "PT_CONTINUE", 83 "PT_KILL", "PT_ATTACH", "PT_DETACH", 84 }; 85 86 87 void dumprecord __P((struct ktr_header *, int, int *, void **, FILE *)); 88 void dumpheader __P((struct ktr_header *, char *, int, int *)); 89 int fread_tail __P((char *, int, int, FILE *)); 90 void ioctldecode __P((u_long)); 91 int ktrsyscall __P((struct ktr_syscall *, int, char *, int, int *)); 92 void ktrsysret __P((struct ktr_sysret *, char *, int, int *)); 93 void ktrnamei __P((char *, int, char *, int, int *)); 94 void ktremul __P((struct ktr_header *, char *, int, char *, int, int *)); 95 void ktrgenio __P((struct ktr_genio *, int, char *, int, int *)); 96 void ktrpsig __P((struct ktr_psig *)); 97 void ktrcsw __P((struct ktr_csw *)); 98 99 #define KTR_BUFSZ 512 100 #define BLEFT (bufsz - (bp - buff)) 101 102 103 void 104 dumprecord(ktr, trpoints, sizep, mp, fp) 105 register struct ktr_header *ktr; 106 int trpoints; 107 int *sizep; 108 void **mp; 109 FILE *fp; 110 { 111 static void *mcopy = NULL; 112 static int linelen = 0, iolinelen = 0; 113 char buff[KTR_BUFSZ], iobuff[KTR_BUFSZ], *bp; 114 int ktrlen, *lenp; 115 void *m; 116 117 if (!ktr) { 118 printf("%s\n", buff); 119 if (*iobuff) 120 printf("%s\n", iobuff); 121 return; 122 } 123 124 if (ktr->ktr_type == KTR_GENIO || ktr->ktr_type == KTR_EMUL) { 125 bp = iobuff; 126 lenp = &iolinelen; 127 } else { 128 bp = buff; 129 lenp = &linelen; 130 } 131 if (!mcopy && (trpoints & (1<<ktr->ktr_type))) 132 dumpheader(ktr, bp, KTR_BUFSZ, lenp); 133 134 if ((ktrlen = ktr->ktr_len) < 0) 135 errx(1, "bogus length 0x%x", ktrlen); 136 m = *mp; 137 if (ktrlen >= *sizep) { 138 while(ktrlen > *sizep) *sizep *= 2; 139 *mp = m = (void *)realloc(m, *sizep); 140 if (m == NULL) 141 errx(1, "realloc: %s", strerror(ENOMEM)); 142 } 143 if (ktrlen && fread_tail(m, ktrlen, 1, fp) == 0) 144 errx(1, "data too short"); 145 if ((trpoints & (1<<ktr->ktr_type)) == 0) 146 return; 147 148 /* update context to match currently processed record */ 149 ectx_sanify(ktr->ktr_pid); 150 151 switch (ktr->ktr_type) 152 { 153 case KTR_SYSCALL: 154 if (ktrsyscall((struct ktr_syscall *)m, 0, bp, KTR_BUFSZ, 155 lenp) == 0) { 156 mcopy = (void *)malloc(ktrlen + 1); 157 bcopy(m, mcopy, ktrlen); 158 return; 159 } 160 break; 161 case KTR_SYSRET: 162 ktrsysret((struct ktr_sysret *)m, bp, KTR_BUFSZ, lenp); 163 if (*iobuff || iolinelen) { 164 fputs(iobuff, stdout); 165 *iobuff = '\0'; 166 iolinelen = 0; 167 } 168 break; 169 case KTR_NAMEI: 170 ktrnamei(m, ktrlen, bp, sizeof(buff), lenp); 171 if (mcopy) { 172 (void) ktrsyscall((struct ktr_syscall *)mcopy, 1, bp, 173 KTR_BUFSZ, lenp); 174 free(mcopy); 175 mcopy = NULL; 176 } 177 break; 178 case KTR_GENIO: 179 ktrgenio((struct ktr_genio *)m, ktrlen, bp, KTR_BUFSZ, lenp); 180 break; 181 case KTR_PSIG: 182 ktrpsig((struct ktr_psig *)m); 183 break; 184 case KTR_CSW: 185 ktrcsw((struct ktr_csw *)m); 186 break; 187 case KTR_EMUL: 188 ktremul(ktr, m, ktrlen, bp, sizeof(buff), lenp); 189 break; 190 } 191 192 if (mcopy) { 193 free(mcopy); 194 mcopy = NULL; 195 } 196 } 197 198 void 199 dumpfile(file, fd, trpoints) 200 const char *file; 201 int fd; 202 int trpoints; 203 { 204 struct ktr_header ktr_header; 205 void *m; 206 FILE *fp; 207 int size; 208 209 m = (void *)malloc(size = 1024); 210 if (m == NULL) 211 errx(1, "malloc: %s", strerror(ENOMEM)); 212 if (!file || !*file) { 213 if (!(fp = fdopen(fd, "r"))) 214 err(1, "fdopen(%d)", fd); 215 } else if (!strcmp(file, "-")) 216 fp = stdin; 217 else if (!(fp = fopen(file, "r"))) 218 err(1, "%s", file); 219 220 while (fread_tail((char *)&ktr_header,sizeof(struct ktr_header),1,fp)) { 221 dumprecord(&ktr_header, trpoints, &size, &m, fp); 222 if (tail) 223 (void)fflush(stdout); 224 } 225 dumprecord(NULL, 0, NULL, NULL, fp); 226 } 227 228 229 int 230 fread_tail(buf, size, num, fp) 231 char *buf; 232 int num, size; 233 FILE *fp; 234 { 235 int i; 236 237 while ((i = fread(buf, size, num, fp)) == 0 && tail) { 238 (void)sleep(1); 239 clearerr(fp); 240 } 241 return (i); 242 } 243 244 void 245 dumpheader(kth, buff, buffsz, lenp) 246 struct ktr_header *kth; 247 char *buff; 248 int buffsz, *lenp; 249 { 250 static struct timeval prevtime; 251 char *bp = buff + *lenp; 252 struct timeval temp; 253 254 if (kth->ktr_type == KTR_SYSRET || kth->ktr_type == KTR_GENIO) 255 return; 256 *lenp = 0; 257 (void)snprintf(bp, buffsz - *lenp, "%6d %-8.*s ", 258 kth->ktr_pid, MAXCOMLEN, kth->ktr_comm); 259 *lenp += strlen(bp); 260 bp = buff + *lenp; 261 262 if (timestamp) { 263 if (timestamp == 2) { 264 timersub(&kth->ktr_time, &prevtime, &temp); 265 prevtime = kth->ktr_time; 266 } else 267 temp = kth->ktr_time; 268 (void)snprintf(bp, buffsz - *lenp, "%ld.%06ld ", 269 (long int)temp.tv_sec, 270 (long int)temp.tv_usec); 271 *lenp += strlen(bp); 272 } 273 } 274 275 void 276 ioctldecode(cmd) 277 u_long cmd; 278 { 279 char dirbuf[4], *dir = dirbuf; 280 281 if (cmd & IOC_OUT) 282 *dir++ = 'W'; 283 if (cmd & IOC_IN) 284 *dir++ = 'R'; 285 *dir = '\0'; 286 287 printf(decimal ? ",_IO%s('%c',%ld" : ",_IO%s('%c',%#lx", 288 dirbuf, (int) ((cmd >> 8) & 0xff), cmd & 0xff); 289 if ((cmd & IOC_VOID) == 0) 290 printf(decimal ? ",%ld)" : ",%#lx)", (cmd >> 16) & 0xff); 291 else 292 printf(")"); 293 } 294 295 int 296 ktrsyscall(ktr, nohdr, buff, bufsz, lenp) 297 register struct ktr_syscall *ktr; 298 int nohdr, bufsz, *lenp; 299 char *buff; 300 { 301 register int argsize = ktr->ktr_argsize; 302 register register_t *ap; 303 char *bp = buff; 304 int eol = 1; 305 306 if (*lenp < bufsz) { 307 bp += *lenp; 308 bzero(bp, BLEFT); 309 } 310 if (!nohdr) { 311 if (ktr->ktr_code >= current->nsysnames || ktr->ktr_code < 0) 312 (void)snprintf(bp, BLEFT, "[%d]", ktr->ktr_code); 313 else 314 (void)snprintf(bp, BLEFT, 315 "%s", current->sysnames[ktr->ktr_code]); 316 bp += strlen(bp); 317 } 318 ap = (register_t *)((char *)ktr + sizeof(struct ktr_syscall)); 319 if (argsize) { 320 char *s = "("; 321 if (fancy && !nohdr) { 322 switch (ktr->ktr_code) { 323 /* 324 * All these have a path as the first param. 325 * The order is same as syscalls.master. 326 */ 327 case SYS_open: 328 case SYS_link: 329 case SYS_unlink: 330 case SYS_chdir: 331 case SYS_mknod: 332 case SYS_chmod: 333 case SYS_chown: 334 case SYS_unmount: 335 case SYS_access: 336 case SYS_chflags: 337 case SYS_acct: 338 case SYS_revoke: 339 case SYS_symlink: 340 case SYS_readlink: 341 case SYS_execve: 342 case SYS_chroot: 343 case SYS_rename: 344 case SYS_mkfifo: 345 case SYS_mkdir: 346 case SYS_rmdir: 347 case SYS_utimes: 348 case SYS_quotactl: 349 case SYS_statfs: 350 case SYS_getfh: 351 case SYS_pathconf: 352 case SYS_truncate: 353 case SYS_undelete: 354 case SYS___posix_rename: 355 case SYS_lchmod: 356 case SYS_lchown: 357 case SYS_lutimes: 358 case SYS___stat13: 359 case SYS___lstat13: 360 case SYS___posix_chown: 361 case SYS___posix_lchown: 362 case SYS_lchflags: 363 if (BLEFT > 1) 364 *bp++ = '('; 365 eol = 0; 366 break; 367 case SYS___sigaction14 : 368 (void)snprintf(bp, BLEFT, "(%s", 369 signals[(int)*ap].name); 370 s = ", "; 371 argsize -= sizeof(register_t); 372 ap++; 373 break; 374 case SYS_ioctl : 375 if (decimal) 376 (void)snprintf(bp, BLEFT, "(%ld", 377 (long)*ap); 378 else 379 (void)snprintf(bp, BLEFT, "(%#lx", 380 (long)*ap); 381 bp += strlen(bp); 382 ap++; 383 argsize -= sizeof(register_t); 384 if ((s = ioctlname(*ap)) != NULL) 385 (void)snprintf(bp, BLEFT, ", %s", s); 386 else 387 ioctldecode(*ap); 388 s = ", "; 389 ap++; 390 argsize -= sizeof(register_t); 391 break; 392 case SYS_ptrace : 393 if (*ap >= 0 && *ap <= 394 sizeof(ptrace_ops) / sizeof(ptrace_ops[0])) 395 (void)snprintf(bp, BLEFT, "(%s", 396 ptrace_ops[*ap]); 397 else 398 (void)snprintf(bp, BLEFT, "(%ld", 399 (long)*ap); 400 s = ", "; 401 ap++; 402 argsize -= sizeof(register_t); 403 break; 404 default : 405 break; 406 } 407 bp += strlen(bp); 408 } 409 if (eol) { 410 while (argsize) { 411 if (!nohdr || strcmp(s, "(")) { 412 if (decimal) 413 (void)snprintf(bp, BLEFT, 414 "%s%ld", s, 415 (long)*ap); 416 else 417 (void)snprintf(bp, BLEFT, 418 "%s%#lx", s, 419 (long)*ap); 420 bp += strlen(bp); 421 } 422 s = ", "; 423 ap++; 424 argsize -= sizeof(register_t); 425 } 426 if (BLEFT > 1) 427 *bp++ = ')'; 428 } 429 } 430 *bp = '\0'; 431 432 *lenp = bp - buff; 433 return eol; 434 } 435 436 void 437 ktrsysret(ktr, buff, buffsz, lenp) 438 struct ktr_sysret *ktr; 439 int buffsz, *lenp; 440 char *buff; 441 { 442 register register_t ret = ktr->ktr_retval; 443 register int error = ktr->ktr_error; 444 445 while (*lenp < 50) 446 buff[(*lenp)++] = ' '; 447 if (error == EJUSTRETURN) 448 strcpy(buff + *lenp, " JUSTRETURN"); 449 else if (error == ERESTART) 450 strcpy(buff + *lenp, " RESTART"); 451 else if (error) { 452 sprintf(buff + *lenp, " Err#%d", error); 453 if (error < MAXERRNOS && error >= -2) 454 sprintf(buff + strlen(buff), " %s",errnos[error].name); 455 } else 456 sprintf(buff + *lenp, " = %ld", (long)ret); 457 strcat(buff + *lenp, "\n"); 458 *lenp = 0; 459 fputs(buff, stdout); 460 *buff = '\0'; 461 } 462 463 void 464 ktrnamei(cp, len, buff, buffsz, lenp) 465 int buffsz, *lenp; 466 char *cp, *buff; 467 { 468 snprintf(buff + *lenp, buffsz - *lenp, "\"%.*s\"", len, cp); 469 *lenp += strlen(buff + *lenp); 470 } 471 472 void 473 ktremul(ktr_header, cp, len, buff, buffsz, lenp) 474 struct ktr_header *ktr_header; 475 int buffsz, *lenp; 476 char *cp, *buff; 477 { 478 bzero(buff + *lenp, buffsz - *lenp); 479 cp[len] = '\0'; 480 snprintf(buff + *lenp, buffsz - *lenp, "emul(%s)\n", cp); 481 *lenp += strlen(buff + *lenp); 482 483 setemul(cp, ktr_header->ktr_pid, 1); 484 } 485 486 void 487 ktrgenio(ktr, len, buff, bufsz, lenp) 488 struct ktr_genio *ktr; 489 int len; 490 char *buff; 491 int bufsz, *lenp; 492 { 493 static int screenwidth = 0; 494 register int datalen = len - sizeof (struct ktr_genio); 495 register char *dp = (char *)ktr + sizeof (struct ktr_genio); 496 register int col = 0; 497 register int width; 498 char visbuf[5], *bp = buff; 499 500 if (*lenp < bufsz) { 501 bp += *lenp; 502 bzero(buff, BLEFT); 503 } else 504 *lenp = 0; 505 if (screenwidth == 0) { 506 struct winsize ws; 507 508 if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 && 509 ws.ws_col > 8) 510 screenwidth = ws.ws_col; 511 else 512 screenwidth = 80; 513 } 514 515 if (maxdata && datalen > maxdata) 516 datalen = maxdata; 517 strcpy(bp, " \""); 518 col = *lenp; 519 col += 8; 520 bp += 8; 521 for (; datalen > 0; datalen--, dp++) { 522 (void) vis(visbuf, *dp, VIS_NL|VIS_TAB|VIS_CSTYLE, *(dp+1)); 523 width = strlen(visbuf); 524 visbuf[4] = '\0'; 525 if (col + width + 2 >= screenwidth) 526 break; 527 col += width; 528 strncpy(bp, visbuf, width); 529 bp += width; 530 if (col + 2 >= screenwidth) 531 break; 532 } 533 strcpy(bp, "\"\n"); 534 *lenp = col + 2; 535 } 536 537 void 538 ktrpsig(psig) 539 struct ktr_psig *psig; 540 { 541 (void)printf("SIG%s ", sys_signame[psig->signo]); 542 if (psig->action == SIG_DFL) 543 (void)printf("SIG_DFL\n"); 544 else { 545 (void)printf("caught handler=0x%lx mask=0x%lx code=0x%x\n", 546 (u_long)psig->action, (unsigned long)psig->mask.__bits[0], 547 psig->code); 548 } 549 } 550 551 void 552 ktrcsw(cs) 553 struct ktr_csw *cs; 554 { 555 (void)printf("%s %s\n", cs->out ? "stop" : "resume", 556 cs->user ? "user" : "kernel"); 557 } 558