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