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