1 /*- 2 * Copyright (c) 1988 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 char copyright[] = 10 "@(#) Copyright (c) 1988 The Regents of the University of California.\n\ 11 All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)kdump.c 5.3 (Berkeley) 01/17/91"; 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 } 141 if (tail) 142 (void)fflush(stdout); 143 } 144 } 145 146 fread_tail(buf, size, num) 147 char *buf; 148 int num, size; 149 { 150 int i; 151 152 while ((i = fread(buf, size, num, stdin)) == 0 && tail) { 153 (void)sleep(1); 154 clearerr(stdin); 155 } 156 return (i); 157 } 158 159 dumpheader(kth) 160 struct ktr_header *kth; 161 { 162 static char unknown[64]; 163 static struct timeval prevtime, temp; 164 char *type; 165 166 switch (kth->ktr_type) { 167 case KTR_SYSCALL: 168 type = "CALL"; 169 break; 170 case KTR_SYSRET: 171 type = "RET "; 172 break; 173 case KTR_NAMEI: 174 type = "NAMI"; 175 break; 176 case KTR_GENIO: 177 type = "GIO "; 178 break; 179 case KTR_PSIG: 180 type = "PSIG"; 181 break; 182 default: 183 (void)sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type); 184 type = unknown; 185 } 186 187 (void)printf("%6d %-8s ", kth->ktr_pid, kth->ktr_comm); 188 if (timestamp) { 189 if (timestamp == 2) { 190 temp = kth->ktr_time; 191 timevalsub(&kth->ktr_time, &prevtime); 192 prevtime = temp; 193 } 194 (void)printf("%ld.%06ld ", 195 kth->ktr_time.tv_sec, kth->ktr_time.tv_usec); 196 } 197 (void)printf("%s ", type); 198 } 199 200 #include <sys/syscall.h> 201 #define KTRACE 202 #include "/sys/kern/syscalls.c" 203 #undef KTRACE 204 int nsyscalls = sizeof (syscallnames) / sizeof (syscallnames[0]); 205 206 static char *ptrace_ops[] = { 207 "PT_TRACE_ME", "PT_READ_I", "PT_READ_D", "PT_READ_U", 208 "PT_WRITE_I", "PT_WRITE_D", "PT_WRITE_U", "PT_CONTINUE", 209 "PT_KILL", "PT_STEP", 210 }; 211 212 ktrsyscall(ktr) 213 register struct ktr_syscall *ktr; 214 { 215 register narg = ktr->ktr_narg; 216 register int *ip; 217 char *ioctlname(); 218 219 if (ktr->ktr_code >= nsyscalls || ktr->ktr_code < 0) 220 (void)printf("[%d]", ktr->ktr_code); 221 else 222 (void)printf("%s", syscallnames[ktr->ktr_code]); 223 ip = (int *)((char *)ktr + sizeof(struct ktr_syscall)); 224 if (narg) { 225 char c = '('; 226 if (fancy) { 227 if (ktr->ktr_code == SYS_ioctl) { 228 char *cp; 229 if (decimal) 230 (void)printf("(%d", *ip); 231 else 232 (void)printf("(%#x", *ip); 233 ip++; 234 narg--; 235 if ((cp = ioctlname(*ip)) != NULL) 236 (void)printf(",%s", cp); 237 else { 238 if (decimal) 239 (void)printf(",%d", *ip); 240 else 241 (void)printf(",%#x ", *ip); 242 } 243 c = ','; 244 ip++; 245 narg--; 246 } else if (ktr->ktr_code == SYS_ptrace) { 247 if (*ip <= PT_STEP && *ip >= 0) 248 (void)printf("(%s", ptrace_ops[*ip]); 249 else 250 (void)printf("(%d", *ip); 251 c = ','; 252 ip++; 253 narg--; 254 } 255 } 256 while (narg) { 257 if (decimal) 258 (void)printf("%c%d", c, *ip); 259 else 260 (void)printf("%c%#x", c, *ip); 261 c = ','; 262 ip++; 263 narg--; 264 } 265 (void)putchar(')'); 266 } 267 (void)putchar('\n'); 268 } 269 270 ktrsysret(ktr) 271 struct ktr_sysret *ktr; 272 { 273 register int ret = ktr->ktr_retval; 274 register int error = ktr->ktr_error; 275 register int code = ktr->ktr_code; 276 277 if (code >= nsyscalls || code < 0) 278 (void)printf("[%d] ", code); 279 else 280 (void)printf("%s ", syscallnames[code]); 281 282 if (error == 0) { 283 if (fancy) { 284 (void)printf("%d", ret); 285 if (ret < 0 || ret > 9) 286 (void)printf("/%#x", ret); 287 } else { 288 if (decimal) 289 (void)printf("%d", ret); 290 else 291 (void)printf("%#x", ret); 292 } 293 } else if (error == ERESTART) 294 (void)printf("RESTART"); 295 else if (error == EJUSTRETURN) 296 (void)printf("JUSTRETURN"); 297 else { 298 (void)printf("-1 errno %d", ktr->ktr_error); 299 if (fancy) 300 (void)printf(" %s", strerror(ktr->ktr_error)); 301 } 302 (void)putchar('\n'); 303 } 304 305 ktrnamei(cp, len) 306 char *cp; 307 { 308 (void)printf("\"%.*s\"\n", len, cp); 309 } 310 311 ktrgenio(ktr, len) 312 struct ktr_genio *ktr; 313 { 314 register int datalen = len - sizeof (struct ktr_genio); 315 register char *dp = (char *)ktr + sizeof (struct ktr_genio); 316 register char *cp; 317 register int col = 0; 318 register width; 319 char visbuf[5]; 320 static screenwidth = 0; 321 322 if (screenwidth == 0) { 323 struct winsize ws; 324 325 if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 && 326 ws.ws_col > 8) 327 screenwidth = ws.ws_col; 328 else 329 screenwidth = 80; 330 } 331 printf("fd %d %s %d bytes\n", ktr->ktr_fd, 332 ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen); 333 if (maxdata && datalen > maxdata) 334 datalen = maxdata; 335 (void)printf(" \""); 336 col = 8; 337 for (;datalen > 0; datalen--, dp++) { 338 (void) vis(visbuf, *dp, VIS_CSTYLE, *(dp+1)); 339 cp = visbuf; 340 /* 341 * Keep track of printables and 342 * space chars (like fold(1)). 343 */ 344 if (col == 0) { 345 (void)putchar('\t'); 346 col = 8; 347 } 348 switch(*cp) { 349 case '\n': 350 col = 0; 351 (void)putchar('\n'); 352 continue; 353 case '\t': 354 width = 8 - (col&07); 355 break; 356 default: 357 width = strlen(cp); 358 } 359 if (col + width > (screenwidth-2)) { 360 (void)printf("\\\n\t"); 361 col = 8; 362 } 363 col += width; 364 do { 365 (void)putchar(*cp++); 366 } while (*cp); 367 } 368 if (col == 0) 369 (void)printf(" "); 370 (void)printf("\"\n"); 371 } 372 373 char *signames[] = { 374 "NULL", "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT", /* 1 - 6 */ 375 "EMT", "FPE", "KILL", "BUS", "SEGV", "SYS", /* 7 - 12 */ 376 "PIPE", "ALRM", "TERM", "URG", "STOP", "TSTP", /* 13 - 18 */ 377 "CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU", /* 19 - 24 */ 378 "XFSZ", "VTALRM", "PROF", "WINCH", "29", "USR1", /* 25 - 30 */ 379 "USR2", NULL, /* 31 - 32 */ 380 }; 381 382 ktrpsig(psig) 383 struct ktr_psig *psig; 384 { 385 (void)printf("SIG%s ", signames[psig->signo]); 386 if (psig->action == SIG_DFL) 387 (void)printf("SIG_DFL\n"); 388 else 389 (void)printf("caught handler=0x%x mask=0x%x code=0x%x\n", 390 (u_int)psig->action, psig->mask, psig->code); 391 } 392 393 usage() 394 { 395 (void)fprintf(stderr, 396 "usage: kdump [-dnlRT] [-f trfile] [-m maxdata] [-t [cnis]]\n"); 397 exit(1); 398 } 399