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