1 /* 2 * Copyright (c) 1988 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 */ 17 18 #ifndef lint 19 char copyright[] = 20 "@(#) Copyright (c) 1988 The Regents of the University of California.\n\ 21 All rights reserved.\n"; 22 #endif /* not lint */ 23 24 #ifndef lint 25 static char sccsid[] = "@(#)kdump.c 1.8 (Berkeley) 05/23/90"; 26 #endif /* not lint */ 27 28 #include <cencode.h> 29 #include "ktrace.h" 30 #include <sys/ioctl.h> 31 32 int timestamp, decimal, fancy = 1, tail, maxdata; 33 char *tracefile = DEF_TRACEFILE; 34 struct ktr_header ktr_header; 35 int size = 1024; /* initial size - grow as needed */ 36 37 #define USAGE \ 38 "usage: kdump [-dnlT] [-t trops] [-f trfile] [-m maxdata]\n\ 39 trops: c = syscalls, n = namei, g = generic-i/o, a = everything\n" 40 41 #define eqs(s1, s2) (strcmp((s1), (s2)) == 0) 42 43 main(argc, argv) 44 char *argv[]; 45 { 46 extern int optind; 47 extern char *optarg; 48 int ch, ktrlen; 49 register char *m; 50 int trpoints = ALL_POINTS; 51 52 while ((ch = getopt(argc,argv,"t:f:dnlTRm:")) != EOF) 53 switch((char)ch) { 54 case 't': 55 trpoints = getpoints(optarg); 56 if (trpoints < 0) { 57 fprintf(stderr, 58 "kdump: unknown trace point in %s\n", 59 optarg); 60 exit(1); 61 } 62 break; 63 case 'f': 64 tracefile = optarg; 65 break; 66 case 'd': 67 decimal = 1; 68 break; 69 case 'n': 70 fancy = 0; 71 break; 72 case 'l': 73 tail = 1; 74 break; 75 case 'T': 76 timestamp = 1; 77 break; 78 case 'R': 79 timestamp = 2; /* relative timestamp */ 80 break; 81 case 'm': 82 maxdata = atoi(optarg); 83 break; 84 default: 85 fprintf(stderr, USAGE); 86 exit(1); 87 } 88 argv += optind, argc -= optind; 89 90 if (argc > 1) { 91 fprintf(stderr, USAGE); 92 exit(1); 93 } 94 if (!eqs(tracefile, "-")) { 95 if (freopen(tracefile, "r", stdin) == NULL) { 96 fprintf(stderr, "kdump: %s: ", tracefile); 97 perror(""); 98 exit(1); 99 } 100 } 101 m = (char *)malloc(size+1); 102 if (m == NULL) { 103 fprintf(stderr, "kdump: ain't gots no memory\n"); 104 exit(1); 105 } 106 while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1, 107 stdin, tail)) { 108 if (trpoints & (1<<ktr_header.ktr_type)) 109 dumpheader(&ktr_header); 110 if ((ktrlen = ktr_header.ktr_len) < 0) { 111 fprintf(stderr, "kdump: bogus length 0x%x\n", 112 ktrlen); 113 exit(1); 114 } 115 if (ktrlen > size) { 116 m = (char *)realloc(m, ktrlen+1); 117 if (m == NULL) { 118 fprintf(stderr,"kdump: out of memory\n"); 119 exit(1); 120 } 121 size = ktrlen; 122 } 123 if (ktrlen && fread_tail(m, ktrlen, 1, stdin, tail) == 0) { 124 fprintf(stderr, "kdump: data too short\n"); 125 exit(1); 126 } 127 if ((trpoints & (1<<ktr_header.ktr_type)) == 0) 128 continue; 129 switch (ktr_header.ktr_type) { 130 case KTR_SYSCALL: 131 ktrsyscall((struct ktr_syscall *)m, ktrlen); 132 break; 133 case KTR_SYSRET: 134 ktrsysret((struct ktr_sysret *)m, ktrlen); 135 break; 136 case KTR_NAMEI: 137 ktrnamei(m, ktrlen); 138 break; 139 case KTR_GENIO: 140 ktrgenio((struct ktr_genio *)m, ktrlen); 141 break; 142 case KTR_PSIG: 143 ktrpsig((struct ktr_psig *)m, ktrlen); 144 break; 145 } 146 if (tail) 147 fflush(stdout); 148 } 149 } 150 151 fread_tail(buf, size, num, stream, tail) 152 char *buf; 153 FILE *stream; 154 { 155 int i; 156 157 while ((i = fread(buf, size, num, stream)) == 0 && tail) { 158 sleep(1); 159 clearerr(stream); 160 } 161 return (i); 162 } 163 164 dumpheader(kth) 165 struct ktr_header *kth; 166 { 167 static char unknown[64]; 168 static struct timeval prevtime, temp; 169 char *type; 170 171 switch (kth->ktr_type) { 172 case KTR_SYSCALL: 173 type = "CALL"; 174 break; 175 case KTR_SYSRET: 176 type = "RET "; 177 break; 178 case KTR_NAMEI: 179 type = "NAMI"; 180 break; 181 case KTR_GENIO: 182 type = "GIO "; 183 break; 184 case KTR_PSIG: 185 type = "PSIG"; 186 break; 187 default: 188 sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type); 189 type = unknown; 190 } 191 192 printf("%6d %-8s ", 193 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 printf("%d.%06d ", kth->ktr_time.tv_sec, kth->ktr_time.tv_usec); 201 } 202 printf("%s ", type); 203 } 204 205 #include <sys/syscall.h> 206 #define KTRACE 207 #include "/sys/kern/syscalls.c" 208 #undef KTRACE 209 int nsyscalls = sizeof (syscallnames) / sizeof (syscallnames[0]); 210 211 ktrsyscall(ktr, len) 212 register struct ktr_syscall *ktr; 213 { 214 register narg = ktr->ktr_narg; 215 register int *ip; 216 char *ioctlname(); 217 218 if (ktr->ktr_code >= nsyscalls || ktr->ktr_code < 0) 219 printf("[%d]", ktr->ktr_code); 220 else 221 printf("%s", syscallnames[ktr->ktr_code]); 222 ip = (int *)((char *)ktr + sizeof(struct ktr_syscall)); 223 if (narg) { 224 char c = '('; 225 if (fancy && ktr->ktr_code == SYS_ioctl) { 226 char *cp; 227 if (decimal) 228 printf("(%d", *ip); 229 else 230 printf("(%#x", *ip); 231 ip++; narg--; 232 if ((cp = ioctlname(*ip)) != NULL) 233 printf(",%s", cp); 234 else { 235 if (decimal) 236 printf(",%d", *ip); 237 else 238 printf(",%#x ", *ip); 239 } 240 c = ','; 241 ip++; narg--; 242 } 243 while (narg) { 244 if (decimal) 245 printf("%c%d", c, *ip); 246 else 247 printf("%c%#x", c, *ip); 248 c = ','; 249 ip++; narg--; 250 } 251 putchar(')'); 252 } 253 putchar('\n'); 254 } 255 256 ktrsysret(ktr, len) 257 struct ktr_sysret *ktr; 258 { 259 extern char *sys_errlist[]; 260 int ret = ktr->ktr_retval; 261 262 if (ktr->ktr_code >= nsyscalls || ktr->ktr_code < 0) 263 printf("[%d] ", ktr->ktr_code); 264 else 265 printf("%s ", syscallnames[ktr->ktr_code]); 266 if (ktr->ktr_eosys == RESTARTSYS) 267 printf("RESTART"); 268 else if (ktr->ktr_error) { 269 printf("-1 errno %d", ktr->ktr_error); 270 if (fancy) 271 printf(" %s", strerror(ktr->ktr_error)); 272 } else { 273 if (fancy) { 274 printf("%d", ret); 275 if (ret < 0 || ret > 9) 276 printf("/%#x", ret); 277 } else { 278 if (decimal) 279 printf("%d", ret); 280 else 281 printf("%#x", ret); 282 } 283 } 284 putchar('\n'); 285 } 286 287 ktrnamei(cp, len) 288 char *cp; 289 { 290 printf("\"%.*s\"\n", len, cp); 291 } 292 293 #define CENC_ALL (CENC_CSTYLE | CENC_GRAPH | CENC_OCTAL) 294 295 ktrgenio(ktr, len) 296 struct ktr_genio *ktr; 297 { 298 register int datalen = len - sizeof (struct ktr_genio); 299 register char *dp = (char *)ktr + sizeof (struct ktr_genio); 300 register char *cp; 301 register int col = 0; 302 register char c; 303 register width; 304 static screenwidth = 0; 305 306 if (screenwidth == 0) { 307 struct winsize ws; 308 309 if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 && 310 ws.ws_col > 8) 311 screenwidth = ws.ws_col; 312 else 313 screenwidth = 80; 314 } 315 printf("fd %d %s %d bytes\n", ktr->ktr_fd, 316 ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen); 317 if (maxdata && datalen > maxdata) 318 datalen = maxdata; 319 printf(" \""); 320 col = 8; 321 for (;datalen > 0; datalen--, dp++) { 322 cp = cencode(*dp, CENC_ALL | CENC_RACHAR, *(dp+1)); 323 if (*cp == '\r') 324 cp = "\\r"; 325 /* 326 * Keep track of printables and 327 * space chars (like fold(1)). 328 */ 329 if (col == 0) { 330 putchar('\t'); 331 col = 8; 332 } 333 switch(*cp) { 334 case '\n': 335 col = 0; 336 putchar('\n'); 337 continue; 338 case '\t': 339 width = 8 - (col&07); 340 break; 341 default: 342 width = strlen(cp); 343 } 344 if (col + width > (screenwidth-2)) { 345 printf("\\\n\t"); 346 col = 8; 347 } 348 col += width; 349 do { 350 putchar(*cp++); 351 } while (*cp); 352 } 353 if (col == 0) 354 printf(" "); 355 printf("\"\n"); 356 } 357 358 359 char *signames[] = { 360 "NULL", "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT", /* 1 - 6 */ 361 "EMT", "FPE", "KILL", "BUS", "SEGV", "SYS", /* 7 - 12 */ 362 "PIPE", "ALRM", "TERM", "URG", "STOP", "TSTP", /* 13 - 18 */ 363 "CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU", /* 19 - 24 */ 364 "XFSZ", "VTALRM", "PROF", "WINCH", "29", "USR1", /* 25 - 30 */ 365 "USR2", NULL, /* 31 - 32 */ 366 }; 367 368 ktrpsig(psig, len) 369 struct ktr_psig *psig; 370 { 371 printf("SIG%s ", signames[psig->signo]); 372 if (psig->action == SIG_DFL) 373 printf("SIG_DFL\n"); 374 else { 375 printf("caught handler=0x%x mask=0x%x code=0x%x\n", 376 psig->action, psig->mask, psig->code); 377 } 378 } 379