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.5 (Berkeley) 12/21/88"; 26 #endif /* not lint */ 27 28 #include "ktrace.h" 29 30 int timestamp, decimal, fancy = 1, loop, maxdata; 31 char *tracefile = DEF_TRACEFILE; 32 struct ktr_header ktr_header; 33 int size = 1024; /* initial size of buffer - will grow as needed */ 34 35 #define USAGE \ 36 "usage: kdump [-dnlT] [-t facilitystring] [-f tracefile] [-m maxdata]\n\ 37 facilities: c = syscalls, n = namei, g = generic-i/o, a = everything\n" 38 39 #define eqs(s1, s2) (strcmp((s1), (s2)) == 0) 40 41 main(argc, argv) 42 char *argv[]; 43 { 44 extern int optind; 45 extern char *optarg; 46 int ch, ktrlen; 47 register char *m; 48 int facs = DEF_FACS; 49 50 while ((ch = getopt(argc,argv,"t:f:dnlTm:")) != EOF) 51 switch((char)ch) { 52 case 't': 53 facs = getfacs(optarg); 54 if (facs < 0) { 55 fprintf(stderr, 56 "kdump: unknown facility in %s\n", 57 optarg); 58 exit(1); 59 } 60 break; 61 case 'f': 62 tracefile = optarg; 63 break; 64 case 'd': 65 decimal = 1; 66 break; 67 case 'n': 68 fancy = 0; 69 break; 70 case 'l': 71 loop = 1; 72 break; 73 case 'T': 74 timestamp = 1; 75 break; 76 case 'm': 77 maxdata = atoi(optarg); 78 break; 79 default: 80 fprintf(stderr, USAGE); 81 exit(1); 82 } 83 argv += optind, argc -= optind; 84 85 if (argc > 1) { 86 fprintf(stderr, USAGE); 87 exit(1); 88 } 89 if (!eqs(tracefile, "-")) { 90 if (freopen(tracefile, "r", stdin) == NULL) { 91 fprintf(stderr, "kdump: %s: ", tracefile); 92 perror(""); 93 exit(1); 94 } 95 } 96 m = (char *)malloc(size); 97 if (m == NULL) { 98 fprintf(stderr, "kdump: ain't gots no memory\n"); 99 exit(1); 100 } 101 while (myfread(&ktr_header, sizeof(struct ktr_header), 1, stdin)) { 102 if (facs & (1<<ktr_header.ktr_type)) 103 dumpheader(&ktr_header); 104 if ((ktrlen = ktr_header.ktr_len) > 80000) { /* XXX */ 105 fprintf(stderr, "kdump: bogus length %d\n", 106 ktrlen); 107 exit(1); 108 } 109 if (ktrlen > size) { 110 m = (char *)realloc(m, ktrlen); 111 if (m == NULL) { 112 fprintf(stderr,"kdump: ain't gots no memory\n"); 113 exit(1); 114 } 115 size = ktrlen; 116 } 117 if (myfread(m, ktrlen, 1, stdin) == 0) { 118 fprintf(stderr, "kdump: out of data\n"); 119 exit(1); 120 } 121 if ((facs & (1<<ktr_header.ktr_type)) == 0) 122 continue; 123 switch (ktr_header.ktr_type) { 124 case KTR_SYSCALL: 125 ktrsyscall((struct ktr_syscall *)m, ktrlen); 126 break; 127 case KTR_SYSRET: 128 ktrsysret((struct ktr_sysret *)m, ktrlen); 129 break; 130 case KTR_NAMEI: 131 ktrnamei(m, ktrlen); 132 break; 133 case KTR_GENIO: 134 ktrgenio((struct ktr_genio *)m, ktrlen); 135 break; 136 } 137 if (loop) 138 fflush(stdout); 139 } 140 } 141 142 myfread(buf, size, num, stream) 143 char *buf; 144 FILE *stream; 145 { 146 int i; 147 again: 148 if (i = fread(buf, size, num, stream)) 149 return (i); 150 else { 151 if (loop) { 152 sleep(1); 153 clearerr(stream); 154 goto again; 155 } else 156 return 0; 157 } 158 } 159 160 dumpheader(kth) 161 struct ktr_header *kth; 162 { 163 static char unknown[64]; 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 default: 180 sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type); 181 type = unknown; 182 } 183 184 printf("%6d %-8s ", 185 kth->ktr_pid, kth->ktr_comm); 186 if (timestamp) 187 printf("%d.%d ", kth->ktr_time.tv_sec, kth->ktr_time.tv_usec); 188 printf("%s ", type); 189 } 190 191 #include <sys/syscall.h> 192 #define KTRACE 193 #include "/sys/sys/syscalls.c" 194 #undef KTRACE 195 int nsyscalls = sizeof (syscallnames) / sizeof (syscallnames[0]); 196 197 ktrsyscall(ktr, len) 198 register struct ktr_syscall *ktr; 199 { 200 register narg = ktr->ktr_narg; 201 register int *ip; 202 char *ioctlname(); 203 204 if (ktr->ktr_code >= nsyscalls || ktr->ktr_code < 0) 205 printf("[%d]", ktr->ktr_code); 206 else 207 printf("%s", syscallnames[ktr->ktr_code]); 208 ip = (int *)((char *)ktr + sizeof(struct ktr_syscall)); 209 if (narg) { 210 char c = '('; 211 if (fancy && ktr->ktr_code == SYS_ioctl) { 212 char *cp; 213 if (decimal) 214 printf("(%d", *ip); 215 else 216 printf("(%#x", *ip); 217 ip++; narg--; 218 if ((cp = ioctlname(*ip)) != NULL) 219 printf(",%s", cp); 220 else { 221 if (decimal) 222 printf(",%d", *ip); 223 else 224 printf(",%#x ", *ip); 225 } 226 c = ','; 227 ip++; narg--; 228 } 229 while (narg) { 230 if (decimal) 231 printf("%c%d", c, *ip); 232 else 233 printf("%c%#x", c, *ip); 234 c = ','; 235 ip++; narg--; 236 } 237 putchar(')'); 238 } 239 putchar('\n'); 240 } 241 242 ktrsysret(ktr, len) 243 struct ktr_sysret *ktr; 244 { 245 extern char *sys_errlist[]; 246 int ret = ktr->ktr_retval; 247 248 if (ktr->ktr_code >= nsyscalls || ktr->ktr_code < 0) 249 printf("[%d] ", ktr->ktr_code); 250 else 251 printf("%s ", syscallnames[ktr->ktr_code]); 252 if (ktr->ktr_error) { 253 printf("-1 errno %d", ktr->ktr_error); 254 if (fancy) 255 printf(" %s", sys_errlist[ktr->ktr_error]); 256 } else { 257 if (fancy) { 258 printf("%d", ret); 259 if (ret < 0 || ret > 9) 260 printf(" %#x", ret); 261 } else { 262 if (decimal) 263 printf("%d", ret); 264 else 265 printf("%#x", ret); 266 } 267 } 268 putchar('\n'); 269 } 270 271 ktrnamei(cp, len) 272 char *cp; 273 { 274 printf("\"%.*s\"\n", len, cp); 275 } 276 277 ktrgenio(ktr, len) 278 struct ktr_genio *ktr; 279 { 280 int datalen = len - sizeof (struct ktr_genio); 281 char *cp = (char *)ktr + sizeof (struct ktr_genio); 282 register int col = 0; 283 register char c; 284 285 printf("fd %d %s %d bytes\n", ktr->ktr_fd, 286 ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen); 287 if (maxdata && datalen > maxdata) 288 datalen = maxdata; 289 for (;datalen > 0; datalen--, cp++) { 290 c = *cp; 291 292 if (col == 0) { 293 putchar('\t'); 294 col = 1; 295 } 296 if (c == '\n' || c == '\t') { 297 if (c == '\n') 298 col = 0; 299 putchar(c); 300 continue; 301 } 302 if (c & 0200) { 303 putchar('M'); 304 putchar('-'); 305 c &= 0177; 306 } 307 if (c < 040 || c == 0177) { 308 putchar('^'); 309 if (c == 0177) 310 putchar('?'); 311 else 312 putchar(c+'@'); 313 } else 314 putchar(c); 315 } 316 if (col != 0) 317 putchar('\n'); 318 } 319