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 static const char rcsid[] = 45 "$FreeBSD$"; 46 #endif /* not lint */ 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 #include <sys/time.h> 55 #include <sys/uio.h> 56 #include <sys/ktrace.h> 57 #include <sys/ioctl.h> 58 #include <sys/ptrace.h> 59 #include <err.h> 60 #include <locale.h> 61 #include <stdio.h> 62 #include <stdlib.h> 63 #include <string.h> 64 #include <unistd.h> 65 #include <vis.h> 66 #include "ktrace.h" 67 68 int timestamp, decimal, fancy = 1, tail, maxdata; 69 char *tracefile = DEF_TRACEFILE; 70 struct ktr_header ktr_header; 71 72 #define eqs(s1, s2) (strcmp((s1), (s2)) == 0) 73 74 main(argc, argv) 75 int argc; 76 char *argv[]; 77 { 78 int ch, ktrlen, size; 79 register void *m; 80 int trpoints = ALL_POINTS; 81 82 (void) setlocale(LC_CTYPE, ""); 83 84 while ((ch = getopt(argc,argv,"f:dlm:nRTt:")) != -1) 85 switch((char)ch) { 86 case 'f': 87 tracefile = optarg; 88 break; 89 case 'd': 90 decimal = 1; 91 break; 92 case 'l': 93 tail = 1; 94 break; 95 case 'm': 96 maxdata = atoi(optarg); 97 break; 98 case 'n': 99 fancy = 0; 100 break; 101 case 'R': 102 timestamp = 2; /* relative timestamp */ 103 break; 104 case 'T': 105 timestamp = 1; 106 break; 107 case 't': 108 trpoints = getpoints(optarg); 109 if (trpoints < 0) 110 errx(1, "unknown trace point in %s", optarg); 111 break; 112 default: 113 usage(); 114 } 115 116 if (argc > optind) 117 usage(); 118 119 m = (void *)malloc(size = 1025); 120 if (m == NULL) 121 errx(1, "%s", strerror(ENOMEM)); 122 if (!freopen(tracefile, "r", stdin)) 123 err(1, "%s", tracefile); 124 while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) { 125 if (trpoints & (1<<ktr_header.ktr_type)) 126 dumpheader(&ktr_header); 127 if ((ktrlen = ktr_header.ktr_len) < 0) 128 errx(1, "bogus length 0x%x", ktrlen); 129 if (ktrlen > size) { 130 m = (void *)realloc(m, ktrlen+1); 131 if (m == NULL) 132 errx(1, "%s", strerror(ENOMEM)); 133 size = ktrlen; 134 } 135 if (ktrlen && fread_tail(m, ktrlen, 1) == 0) 136 errx(1, "data too short"); 137 if ((trpoints & (1<<ktr_header.ktr_type)) == 0) 138 continue; 139 switch (ktr_header.ktr_type) { 140 case KTR_SYSCALL: 141 ktrsyscall((struct ktr_syscall *)m); 142 break; 143 case KTR_SYSRET: 144 ktrsysret((struct ktr_sysret *)m); 145 break; 146 case KTR_NAMEI: 147 ktrnamei(m, ktrlen); 148 break; 149 case KTR_GENIO: 150 ktrgenio((struct ktr_genio *)m, ktrlen); 151 break; 152 case KTR_PSIG: 153 ktrpsig((struct ktr_psig *)m); 154 break; 155 case KTR_CSW: 156 ktrcsw((struct ktr_csw *)m); 157 break; 158 case KTR_USER: 159 ktruser(ktrlen, m); 160 break; 161 } 162 if (tail) 163 (void)fflush(stdout); 164 } 165 } 166 167 fread_tail(buf, size, num) 168 char *buf; 169 int num, size; 170 { 171 int i; 172 173 while ((i = fread(buf, size, num, stdin)) == 0 && tail) { 174 (void)sleep(1); 175 clearerr(stdin); 176 } 177 return (i); 178 } 179 180 dumpheader(kth) 181 struct ktr_header *kth; 182 { 183 static char unknown[64]; 184 static struct timeval prevtime, temp; 185 char *type; 186 187 switch (kth->ktr_type) { 188 case KTR_SYSCALL: 189 type = "CALL"; 190 break; 191 case KTR_SYSRET: 192 type = "RET "; 193 break; 194 case KTR_NAMEI: 195 type = "NAMI"; 196 break; 197 case KTR_GENIO: 198 type = "GIO "; 199 break; 200 case KTR_PSIG: 201 type = "PSIG"; 202 break; 203 case KTR_CSW: 204 type = "CSW"; 205 break; 206 case KTR_USER: 207 type = "USER"; 208 break; 209 default: 210 (void)sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type); 211 type = unknown; 212 } 213 214 (void)printf("%6d %-8.*s ", kth->ktr_pid, MAXCOMLEN, kth->ktr_comm); 215 if (timestamp) { 216 if (timestamp == 2) { 217 temp = kth->ktr_time; 218 timevalsub(&kth->ktr_time, &prevtime); 219 prevtime = temp; 220 } 221 (void)printf("%ld.%06ld ", 222 kth->ktr_time.tv_sec, kth->ktr_time.tv_usec); 223 } 224 (void)printf("%s ", type); 225 } 226 227 #include <sys/syscall.h> 228 #define KTRACE 229 #include <sys/kern/syscalls.c> 230 #undef KTRACE 231 int nsyscalls = sizeof (syscallnames) / sizeof (syscallnames[0]); 232 233 static char *ptrace_ops[] = { 234 "PT_TRACE_ME", "PT_READ_I", "PT_READ_D", "PT_READ_U", 235 "PT_WRITE_I", "PT_WRITE_D", "PT_WRITE_U", "PT_CONTINUE", 236 "PT_KILL", "PT_STEP", "PT_ATTACH", "PT_DETACH", 237 }; 238 239 ktrsyscall(ktr) 240 register struct ktr_syscall *ktr; 241 { 242 register narg = ktr->ktr_narg; 243 register register_t *ip; 244 char *ioctlname(); 245 246 if (ktr->ktr_code >= nsyscalls || ktr->ktr_code < 0) 247 (void)printf("[%d]", ktr->ktr_code); 248 else 249 (void)printf("%s", syscallnames[ktr->ktr_code]); 250 ip = &ktr->ktr_args[0]; 251 if (narg) { 252 char c = '('; 253 if (fancy) { 254 if (ktr->ktr_code == SYS_ioctl) { 255 char *cp; 256 if (decimal) 257 (void)printf("(%ld", (long)*ip); 258 else 259 (void)printf("(%#lx", (long)*ip); 260 ip++; 261 narg--; 262 if ((cp = ioctlname(*ip)) != NULL) 263 (void)printf(",%s", cp); 264 else { 265 if (decimal) 266 (void)printf(",%ld", (long)*ip); 267 else 268 (void)printf(",%#lx ", (long)*ip); 269 } 270 c = ','; 271 ip++; 272 narg--; 273 } else if (ktr->ktr_code == SYS_ptrace) { 274 if (*ip < sizeof(ptrace_ops) / 275 sizeof(ptrace_ops[0]) && *ip >= 0) 276 (void)printf("(%s", ptrace_ops[*ip]); 277 #ifdef PT_GETREGS 278 else if (*ip == PT_GETREGS) 279 (void)printf("(%s", "PT_GETREGS"); 280 #endif 281 #ifdef PT_SETREGS 282 else if (*ip == PT_SETREGS) 283 (void)printf("(%s", "PT_SETREGS"); 284 #endif 285 #ifdef PT_GETFPREGS 286 else if (*ip == PT_GETFPREGS) 287 (void)printf("(%s", "PT_GETFPREGS"); 288 #endif 289 #ifdef PT_SETFPREGS 290 else if (*ip == PT_SETFPREGS) 291 (void)printf("(%s", "PT_SETFPREGS"); 292 #endif 293 #ifdef PT_GETDBREGS 294 else if (*ip == PT_GETDBREGS) 295 (void)printf("(%s", "PT_GETDBREGS"); 296 #endif 297 #ifdef PT_SETDBREGS 298 else if (*ip == PT_SETDBREGS) 299 (void)printf("(%s", "PT_SETDBREGS"); 300 #endif 301 else 302 (void)printf("(%ld", (long)*ip); 303 c = ','; 304 ip++; 305 narg--; 306 } 307 } 308 while (narg) { 309 if (decimal) 310 (void)printf("%c%ld", c, (long)*ip); 311 else 312 (void)printf("%c%#lx", c, (long)*ip); 313 c = ','; 314 ip++; 315 narg--; 316 } 317 (void)putchar(')'); 318 } 319 (void)putchar('\n'); 320 } 321 322 ktrsysret(ktr) 323 struct ktr_sysret *ktr; 324 { 325 register register_t ret = ktr->ktr_retval; 326 register int error = ktr->ktr_error; 327 register int code = ktr->ktr_code; 328 329 if (code >= nsyscalls || code < 0) 330 (void)printf("[%d] ", code); 331 else 332 (void)printf("%s ", syscallnames[code]); 333 334 if (error == 0) { 335 if (fancy) { 336 (void)printf("%d", ret); 337 if (ret < 0 || ret > 9) 338 (void)printf("/%#lx", (long)ret); 339 } else { 340 if (decimal) 341 (void)printf("%ld", (long)ret); 342 else 343 (void)printf("%#lx", (long)ret); 344 } 345 } else if (error == ERESTART) 346 (void)printf("RESTART"); 347 else if (error == EJUSTRETURN) 348 (void)printf("JUSTRETURN"); 349 else { 350 (void)printf("-1 errno %d", ktr->ktr_error); 351 if (fancy) 352 (void)printf(" %s", strerror(ktr->ktr_error)); 353 } 354 (void)putchar('\n'); 355 } 356 357 ktrnamei(cp, len) 358 char *cp; 359 { 360 (void)printf("\"%.*s\"\n", len, cp); 361 } 362 363 ktrgenio(ktr, len) 364 struct ktr_genio *ktr; 365 { 366 register int datalen = len - sizeof (struct ktr_genio); 367 register char *dp = (char *)ktr + sizeof (struct ktr_genio); 368 register char *cp; 369 register int col = 0; 370 register width; 371 char visbuf[5]; 372 static screenwidth = 0; 373 374 if (screenwidth == 0) { 375 struct winsize ws; 376 377 if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 && 378 ws.ws_col > 8) 379 screenwidth = ws.ws_col; 380 else 381 screenwidth = 80; 382 } 383 printf("fd %d %s %d byte%s\n", ktr->ktr_fd, 384 ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen, 385 datalen == 1 ? "" : "s"); 386 if (maxdata && datalen > maxdata) 387 datalen = maxdata; 388 (void)printf(" \""); 389 col = 8; 390 for (;datalen > 0; datalen--, dp++) { 391 (void) vis(visbuf, *dp, VIS_CSTYLE, *(dp+1)); 392 cp = visbuf; 393 /* 394 * Keep track of printables and 395 * space chars (like fold(1)). 396 */ 397 if (col == 0) { 398 (void)putchar('\t'); 399 col = 8; 400 } 401 switch(*cp) { 402 case '\n': 403 col = 0; 404 (void)putchar('\n'); 405 continue; 406 case '\t': 407 width = 8 - (col&07); 408 break; 409 default: 410 width = strlen(cp); 411 } 412 if (col + width > (screenwidth-2)) { 413 (void)printf("\\\n\t"); 414 col = 8; 415 } 416 col += width; 417 do { 418 (void)putchar(*cp++); 419 } while (*cp); 420 } 421 if (col == 0) 422 (void)printf(" "); 423 (void)printf("\"\n"); 424 } 425 426 char *signames[] = { 427 "NULL", "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT", /* 1 - 6 */ 428 "EMT", "FPE", "KILL", "BUS", "SEGV", "SYS", /* 7 - 12 */ 429 "PIPE", "ALRM", "TERM", "URG", "STOP", "TSTP", /* 13 - 18 */ 430 "CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU", /* 19 - 24 */ 431 "XFSZ", "VTALRM", "PROF", "WINCH", "29", "USR1", /* 25 - 30 */ 432 "USR2", NULL, /* 31 - 32 */ 433 }; 434 435 ktrpsig(psig) 436 struct ktr_psig *psig; 437 { 438 (void)printf("SIG%s ", signames[psig->signo]); 439 if (psig->action == SIG_DFL) 440 (void)printf("SIG_DFL\n"); 441 else 442 (void)printf("caught handler=0x%lx mask=0x%x code=0x%x\n", 443 (u_long)psig->action, psig->mask, psig->code); 444 } 445 446 ktrcsw(cs) 447 struct ktr_csw *cs; 448 { 449 (void)printf("%s %s\n", cs->out ? "stop" : "resume", 450 cs->user ? "user" : "kernel"); 451 } 452 453 ktruser(len, p) 454 int len; 455 unsigned char *p; 456 { 457 (void)printf("%d ", len); 458 while (len--) 459 (void)printf(" %02x", *p++); 460 (void)printf("\n"); 461 462 } 463 464 usage() 465 { 466 (void)fprintf(stderr, 467 "usage: kdump [-dnlRT] [-f trfile] [-m maxdata] [-t [cnisuw]]\n"); 468 exit(1); 469 } 470