1 /*- 2 * Copyright (c) 1988, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #ifndef lint 35 static const char copyright[] = 36 "@(#) Copyright (c) 1988, 1993\n\ 37 The Regents of the University of California. All rights reserved.\n"; 38 #endif /* not lint */ 39 40 #ifndef lint 41 #if 0 42 static char sccsid[] = "@(#)kdump.c 8.1 (Berkeley) 6/6/93"; 43 #endif 44 #endif /* not lint */ 45 #include <sys/cdefs.h> 46 __FBSDID("$FreeBSD$"); 47 48 #define _KERNEL 49 extern int errno; 50 #include <sys/errno.h> 51 #undef _KERNEL 52 #include <sys/param.h> 53 #include <sys/errno.h> 54 #define _KERNEL 55 #include <sys/time.h> 56 #undef _KERNEL 57 #include <sys/uio.h> 58 #include <sys/ktrace.h> 59 #include <sys/ioctl.h> 60 #include <sys/ptrace.h> 61 #include <err.h> 62 #include <locale.h> 63 #include <stdio.h> 64 #include <stdlib.h> 65 #include <string.h> 66 #include <unistd.h> 67 #include <vis.h> 68 #include "ktrace.h" 69 70 int fread_tail(void *, int, int); 71 void dumpheader(struct ktr_header *); 72 void ktrsyscall(struct ktr_syscall *); 73 void ktrsysret(struct ktr_sysret *); 74 void ktrnamei(char *, int); 75 void ktrgenio(struct ktr_genio *, int); 76 void ktrpsig(struct ktr_psig *); 77 void ktrcsw(struct ktr_csw *); 78 void ktruser(int, unsigned char *); 79 void usage(void); 80 81 int timestamp, decimal, fancy = 1, tail, maxdata; 82 const char *tracefile = DEF_TRACEFILE; 83 struct ktr_header ktr_header; 84 85 #define eqs(s1, s2) (strcmp((s1), (s2)) == 0) 86 87 int 88 main(int argc, char *argv[]) 89 { 90 int ch, ktrlen, size; 91 void *m; 92 int trpoints = ALL_POINTS; 93 int drop_logged; 94 95 (void) setlocale(LC_CTYPE, ""); 96 97 while ((ch = getopt(argc,argv,"f:dlm:nRTt:")) != -1) 98 switch((char)ch) { 99 case 'f': 100 tracefile = optarg; 101 break; 102 case 'd': 103 decimal = 1; 104 break; 105 case 'l': 106 tail = 1; 107 break; 108 case 'm': 109 maxdata = atoi(optarg); 110 break; 111 case 'n': 112 fancy = 0; 113 break; 114 case 'R': 115 timestamp = 2; /* relative timestamp */ 116 break; 117 case 'T': 118 timestamp = 1; 119 break; 120 case 't': 121 trpoints = getpoints(optarg); 122 if (trpoints < 0) 123 errx(1, "unknown trace point in %s", optarg); 124 break; 125 default: 126 usage(); 127 } 128 129 if (argc > optind) 130 usage(); 131 132 m = (void *)malloc(size = 1025); 133 if (m == NULL) 134 errx(1, "%s", strerror(ENOMEM)); 135 if (!freopen(tracefile, "r", stdin)) 136 err(1, "%s", tracefile); 137 drop_logged = 0; 138 while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) { 139 if (ktr_header.ktr_type & KTR_DROP) { 140 ktr_header.ktr_type &= ~KTR_DROP; 141 if (!drop_logged) { 142 (void)printf("%6d %-8.*s Events dropped.\n", 143 ktr_header.ktr_pid, MAXCOMLEN, 144 ktr_header.ktr_comm); 145 drop_logged = 1; 146 } 147 } 148 if (trpoints & (1<<ktr_header.ktr_type)) 149 dumpheader(&ktr_header); 150 if ((ktrlen = ktr_header.ktr_len) < 0) 151 errx(1, "bogus length 0x%x", ktrlen); 152 if (ktrlen > size) { 153 m = (void *)realloc(m, ktrlen+1); 154 if (m == NULL) 155 errx(1, "%s", strerror(ENOMEM)); 156 size = ktrlen; 157 } 158 if (ktrlen && fread_tail(m, ktrlen, 1) == 0) 159 errx(1, "data too short"); 160 if ((trpoints & (1<<ktr_header.ktr_type)) == 0) 161 continue; 162 drop_logged = 0; 163 switch (ktr_header.ktr_type) { 164 case KTR_SYSCALL: 165 ktrsyscall((struct ktr_syscall *)m); 166 break; 167 case KTR_SYSRET: 168 ktrsysret((struct ktr_sysret *)m); 169 break; 170 case KTR_NAMEI: 171 ktrnamei(m, ktrlen); 172 break; 173 case KTR_GENIO: 174 ktrgenio((struct ktr_genio *)m, ktrlen); 175 break; 176 case KTR_PSIG: 177 ktrpsig((struct ktr_psig *)m); 178 break; 179 case KTR_CSW: 180 ktrcsw((struct ktr_csw *)m); 181 break; 182 case KTR_USER: 183 ktruser(ktrlen, m); 184 break; 185 default: 186 printf("\n"); 187 break; 188 } 189 if (tail) 190 (void)fflush(stdout); 191 } 192 return 0; 193 } 194 195 int 196 fread_tail(void *buf, int size, int num) 197 { 198 int i; 199 200 while ((i = fread(buf, size, num, stdin)) == 0 && tail) { 201 (void)sleep(1); 202 clearerr(stdin); 203 } 204 return (i); 205 } 206 207 void 208 dumpheader(struct ktr_header *kth) 209 { 210 static char unknown[64]; 211 static struct timeval prevtime, temp; 212 const char *type; 213 214 switch (kth->ktr_type) { 215 case KTR_SYSCALL: 216 type = "CALL"; 217 break; 218 case KTR_SYSRET: 219 type = "RET "; 220 break; 221 case KTR_NAMEI: 222 type = "NAMI"; 223 break; 224 case KTR_GENIO: 225 type = "GIO "; 226 break; 227 case KTR_PSIG: 228 type = "PSIG"; 229 break; 230 case KTR_CSW: 231 type = "CSW"; 232 break; 233 case KTR_USER: 234 type = "USER"; 235 break; 236 default: 237 (void)sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type); 238 type = unknown; 239 } 240 241 (void)printf("%6d %-8.*s ", kth->ktr_pid, MAXCOMLEN, kth->ktr_comm); 242 if (timestamp) { 243 if (timestamp == 2) { 244 temp = kth->ktr_time; 245 timevalsub(&kth->ktr_time, &prevtime); 246 prevtime = temp; 247 } 248 (void)printf("%ld.%06ld ", 249 kth->ktr_time.tv_sec, kth->ktr_time.tv_usec); 250 } 251 (void)printf("%s ", type); 252 } 253 254 #include <sys/syscall.h> 255 #define KTRACE 256 #include <sys/kern/syscalls.c> 257 #undef KTRACE 258 int nsyscalls = sizeof (syscallnames) / sizeof (syscallnames[0]); 259 260 static const char *ptrace_ops[] = { 261 "PT_TRACE_ME", "PT_READ_I", "PT_READ_D", "PT_READ_U", 262 "PT_WRITE_I", "PT_WRITE_D", "PT_WRITE_U", "PT_CONTINUE", 263 "PT_KILL", "PT_STEP", "PT_ATTACH", "PT_DETACH", 264 }; 265 266 void 267 ktrsyscall(struct ktr_syscall *ktr) 268 { 269 int narg = ktr->ktr_narg; 270 register_t *ip; 271 const char *ioctlname(u_long); 272 273 if (ktr->ktr_code >= nsyscalls || ktr->ktr_code < 0) 274 (void)printf("[%d]", ktr->ktr_code); 275 else 276 (void)printf("%s", syscallnames[ktr->ktr_code]); 277 ip = &ktr->ktr_args[0]; 278 if (narg) { 279 char c = '('; 280 if (fancy) { 281 if (ktr->ktr_code == SYS_ioctl) { 282 const char *cp; 283 if (decimal) 284 (void)printf("(%ld", (long)*ip); 285 else 286 (void)printf("(%#lx", (long)*ip); 287 ip++; 288 narg--; 289 if ((cp = ioctlname(*ip)) != NULL) 290 (void)printf(",%s", cp); 291 else { 292 if (decimal) 293 (void)printf(",%ld", (long)*ip); 294 else 295 (void)printf(",%#lx ", (long)*ip); 296 } 297 c = ','; 298 ip++; 299 narg--; 300 } else if (ktr->ktr_code == SYS_ptrace) { 301 if ((size_t)*ip < sizeof(ptrace_ops) / 302 sizeof(ptrace_ops[0]) && *ip >= 0) 303 (void)printf("(%s", ptrace_ops[*ip]); 304 #ifdef PT_GETREGS 305 else if (*ip == PT_GETREGS) 306 (void)printf("(%s", "PT_GETREGS"); 307 #endif 308 #ifdef PT_SETREGS 309 else if (*ip == PT_SETREGS) 310 (void)printf("(%s", "PT_SETREGS"); 311 #endif 312 #ifdef PT_GETFPREGS 313 else if (*ip == PT_GETFPREGS) 314 (void)printf("(%s", "PT_GETFPREGS"); 315 #endif 316 #ifdef PT_SETFPREGS 317 else if (*ip == PT_SETFPREGS) 318 (void)printf("(%s", "PT_SETFPREGS"); 319 #endif 320 #ifdef PT_GETDBREGS 321 else if (*ip == PT_GETDBREGS) 322 (void)printf("(%s", "PT_GETDBREGS"); 323 #endif 324 #ifdef PT_SETDBREGS 325 else if (*ip == PT_SETDBREGS) 326 (void)printf("(%s", "PT_SETDBREGS"); 327 #endif 328 else 329 (void)printf("(%ld", (long)*ip); 330 c = ','; 331 ip++; 332 narg--; 333 } 334 } 335 while (narg) { 336 if (decimal) 337 (void)printf("%c%ld", c, (long)*ip); 338 else 339 (void)printf("%c%#lx", c, (long)*ip); 340 c = ','; 341 ip++; 342 narg--; 343 } 344 (void)putchar(')'); 345 } 346 (void)putchar('\n'); 347 } 348 349 void 350 ktrsysret(struct ktr_sysret *ktr) 351 { 352 register_t ret = ktr->ktr_retval; 353 int error = ktr->ktr_error; 354 int code = ktr->ktr_code; 355 356 if (code >= nsyscalls || code < 0) 357 (void)printf("[%d] ", code); 358 else 359 (void)printf("%s ", syscallnames[code]); 360 361 if (error == 0) { 362 if (fancy) { 363 (void)printf("%d", ret); 364 if (ret < 0 || ret > 9) 365 (void)printf("/%#lx", (long)ret); 366 } else { 367 if (decimal) 368 (void)printf("%ld", (long)ret); 369 else 370 (void)printf("%#lx", (long)ret); 371 } 372 } else if (error == ERESTART) 373 (void)printf("RESTART"); 374 else if (error == EJUSTRETURN) 375 (void)printf("JUSTRETURN"); 376 else { 377 (void)printf("-1 errno %d", ktr->ktr_error); 378 if (fancy) 379 (void)printf(" %s", strerror(ktr->ktr_error)); 380 } 381 (void)putchar('\n'); 382 } 383 384 void 385 ktrnamei(char *cp, int len) 386 { 387 (void)printf("\"%.*s\"\n", len, cp); 388 } 389 390 void 391 ktrgenio(struct ktr_genio *ktr, int len) 392 { 393 int datalen = len - sizeof (struct ktr_genio); 394 char *dp = (char *)ktr + sizeof (struct ktr_genio); 395 char *cp; 396 int col = 0; 397 int width; 398 char visbuf[5]; 399 static int screenwidth = 0; 400 401 if (screenwidth == 0) { 402 struct winsize ws; 403 404 if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 && 405 ws.ws_col > 8) 406 screenwidth = ws.ws_col; 407 else 408 screenwidth = 80; 409 } 410 printf("fd %d %s %d byte%s\n", ktr->ktr_fd, 411 ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen, 412 datalen == 1 ? "" : "s"); 413 if (maxdata && datalen > maxdata) 414 datalen = maxdata; 415 (void)printf(" \""); 416 col = 8; 417 for (;datalen > 0; datalen--, dp++) { 418 (void) vis(visbuf, *dp, VIS_CSTYLE, *(dp+1)); 419 cp = visbuf; 420 /* 421 * Keep track of printables and 422 * space chars (like fold(1)). 423 */ 424 if (col == 0) { 425 (void)putchar('\t'); 426 col = 8; 427 } 428 switch(*cp) { 429 case '\n': 430 col = 0; 431 (void)putchar('\n'); 432 continue; 433 case '\t': 434 width = 8 - (col&07); 435 break; 436 default: 437 width = strlen(cp); 438 } 439 if (col + width > (screenwidth-2)) { 440 (void)printf("\\\n\t"); 441 col = 8; 442 } 443 col += width; 444 do { 445 (void)putchar(*cp++); 446 } while (*cp); 447 } 448 if (col == 0) 449 (void)printf(" "); 450 (void)printf("\"\n"); 451 } 452 453 const char *signames[] = { 454 "NULL", "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT", /* 1 - 6 */ 455 "EMT", "FPE", "KILL", "BUS", "SEGV", "SYS", /* 7 - 12 */ 456 "PIPE", "ALRM", "TERM", "URG", "STOP", "TSTP", /* 13 - 18 */ 457 "CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU", /* 19 - 24 */ 458 "XFSZ", "VTALRM", "PROF", "WINCH", "29", "USR1", /* 25 - 30 */ 459 "USR2", NULL, /* 31 - 32 */ 460 }; 461 462 void 463 ktrpsig(struct ktr_psig *psig) 464 { 465 (void)printf("SIG%s ", signames[psig->signo]); 466 if (psig->action == SIG_DFL) 467 (void)printf("SIG_DFL\n"); 468 else { 469 (void)printf("caught handler=0x%lx mask=0x%x code=0x%x\n", 470 (u_long)psig->action, psig->mask.__bits[0], psig->code); 471 } 472 } 473 474 void 475 ktrcsw(struct ktr_csw *cs) 476 { 477 (void)printf("%s %s\n", cs->out ? "stop" : "resume", 478 cs->user ? "user" : "kernel"); 479 } 480 481 void 482 ktruser(int len, unsigned char *p) 483 { 484 (void)printf("%d ", len); 485 while (len--) 486 (void)printf(" %02x", *p++); 487 (void)printf("\n"); 488 489 } 490 491 void 492 usage(void) 493 { 494 (void)fprintf(stderr, 495 "usage: kdump [-dnlRT] [-f trfile] [-m maxdata] [-t [cnisuw]]\n"); 496 exit(1); 497 } 498