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