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.1 (Berkeley) 06/06/93"; 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 narg = ktr->ktr_narg; 222 register int *ip; 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 ip = (int *)((char *)ktr + sizeof(struct ktr_syscall)); 230 if (narg) { 231 char c = '('; 232 if (fancy) { 233 if (ktr->ktr_code == SYS_ioctl) { 234 char *cp; 235 if (decimal) 236 (void)printf("(%d", *ip); 237 else 238 (void)printf("(%#x", *ip); 239 ip++; 240 narg--; 241 if ((cp = ioctlname(*ip)) != NULL) 242 (void)printf(",%s", cp); 243 else { 244 if (decimal) 245 (void)printf(",%d", *ip); 246 else 247 (void)printf(",%#x ", *ip); 248 } 249 c = ','; 250 ip++; 251 narg--; 252 } else if (ktr->ktr_code == SYS_ptrace) { 253 if (*ip <= PT_STEP && *ip >= 0) 254 (void)printf("(%s", ptrace_ops[*ip]); 255 else 256 (void)printf("(%d", *ip); 257 c = ','; 258 ip++; 259 narg--; 260 } 261 } 262 while (narg) { 263 if (decimal) 264 (void)printf("%c%d", c, *ip); 265 else 266 (void)printf("%c%#x", c, *ip); 267 c = ','; 268 ip++; 269 narg--; 270 } 271 (void)putchar(')'); 272 } 273 (void)putchar('\n'); 274 } 275 276 ktrsysret(ktr) 277 struct ktr_sysret *ktr; 278 { 279 register int ret = ktr->ktr_retval; 280 register int error = ktr->ktr_error; 281 register int code = ktr->ktr_code; 282 283 if (code >= nsyscalls || code < 0) 284 (void)printf("[%d] ", code); 285 else 286 (void)printf("%s ", syscallnames[code]); 287 288 if (error == 0) { 289 if (fancy) { 290 (void)printf("%d", ret); 291 if (ret < 0 || ret > 9) 292 (void)printf("/%#x", ret); 293 } else { 294 if (decimal) 295 (void)printf("%d", ret); 296 else 297 (void)printf("%#x", ret); 298 } 299 } else if (error == ERESTART) 300 (void)printf("RESTART"); 301 else if (error == EJUSTRETURN) 302 (void)printf("JUSTRETURN"); 303 else { 304 (void)printf("-1 errno %d", ktr->ktr_error); 305 if (fancy) 306 (void)printf(" %s", strerror(ktr->ktr_error)); 307 } 308 (void)putchar('\n'); 309 } 310 311 ktrnamei(cp, len) 312 char *cp; 313 { 314 (void)printf("\"%.*s\"\n", len, cp); 315 } 316 317 ktrgenio(ktr, len) 318 struct ktr_genio *ktr; 319 { 320 register int datalen = len - sizeof (struct ktr_genio); 321 register char *dp = (char *)ktr + sizeof (struct ktr_genio); 322 register char *cp; 323 register int col = 0; 324 register width; 325 char visbuf[5]; 326 static screenwidth = 0; 327 328 if (screenwidth == 0) { 329 struct winsize ws; 330 331 if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 && 332 ws.ws_col > 8) 333 screenwidth = ws.ws_col; 334 else 335 screenwidth = 80; 336 } 337 printf("fd %d %s %d bytes\n", ktr->ktr_fd, 338 ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen); 339 if (maxdata && datalen > maxdata) 340 datalen = maxdata; 341 (void)printf(" \""); 342 col = 8; 343 for (;datalen > 0; datalen--, dp++) { 344 (void) vis(visbuf, *dp, VIS_CSTYLE, *(dp+1)); 345 cp = visbuf; 346 /* 347 * Keep track of printables and 348 * space chars (like fold(1)). 349 */ 350 if (col == 0) { 351 (void)putchar('\t'); 352 col = 8; 353 } 354 switch(*cp) { 355 case '\n': 356 col = 0; 357 (void)putchar('\n'); 358 continue; 359 case '\t': 360 width = 8 - (col&07); 361 break; 362 default: 363 width = strlen(cp); 364 } 365 if (col + width > (screenwidth-2)) { 366 (void)printf("\\\n\t"); 367 col = 8; 368 } 369 col += width; 370 do { 371 (void)putchar(*cp++); 372 } while (*cp); 373 } 374 if (col == 0) 375 (void)printf(" "); 376 (void)printf("\"\n"); 377 } 378 379 char *signames[] = { 380 "NULL", "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT", /* 1 - 6 */ 381 "EMT", "FPE", "KILL", "BUS", "SEGV", "SYS", /* 7 - 12 */ 382 "PIPE", "ALRM", "TERM", "URG", "STOP", "TSTP", /* 13 - 18 */ 383 "CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU", /* 19 - 24 */ 384 "XFSZ", "VTALRM", "PROF", "WINCH", "29", "USR1", /* 25 - 30 */ 385 "USR2", NULL, /* 31 - 32 */ 386 }; 387 388 ktrpsig(psig) 389 struct ktr_psig *psig; 390 { 391 (void)printf("SIG%s ", signames[psig->signo]); 392 if (psig->action == SIG_DFL) 393 (void)printf("SIG_DFL\n"); 394 else 395 (void)printf("caught handler=0x%x mask=0x%x code=0x%x\n", 396 (u_int)psig->action, psig->mask, psig->code); 397 } 398 399 ktrcsw(cs) 400 struct ktr_csw *cs; 401 { 402 (void)printf("%s %s\n", cs->out ? "stop" : "resume", 403 cs->user ? "user" : "kernel"); 404 } 405 406 usage() 407 { 408 (void)fprintf(stderr, 409 "usage: kdump [-dnlRT] [-f trfile] [-m maxdata] [-t [cnis]]\n"); 410 exit(1); 411 } 412