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