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