1 /*- 2 * Copyright (c) 1988, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#) Copyright (c) 1988, 1993 The Regents of the University of California. All rights reserved. 34 * @(#)kdump.c 8.1 (Berkeley) 6/6/93 35 * $FreeBSD: src/usr.bin/kdump/kdump.c,v 1.17 1999/12/29 05:05:33 peter Exp $ 36 * $DragonFly: src/usr.bin/kdump/kdump.c,v 1.3 2003/08/27 03:21:50 dillon Exp $ 37 */ 38 39 #define _KERNEL_STRUCTURES 40 41 #include <sys/errno.h> 42 #include <sys/param.h> 43 #include <sys/errno.h> 44 #include <sys/time.h> 45 #include <sys/uio.h> 46 #include <sys/ktrace.h> 47 #include <sys/ioctl.h> 48 #include <sys/ptrace.h> 49 #include <err.h> 50 #include <locale.h> 51 #include <stdio.h> 52 #include <stdlib.h> 53 #include <string.h> 54 #include <unistd.h> 55 #include <vis.h> 56 #include "ktrace.h" 57 58 int timestamp, decimal, fancy = 1, tail, maxdata; 59 char *tracefile = DEF_TRACEFILE; 60 struct ktr_header ktr_header; 61 62 #define eqs(s1, s2) (strcmp((s1), (s2)) == 0) 63 64 main(argc, argv) 65 int argc; 66 char *argv[]; 67 { 68 int ch, ktrlen, size; 69 register void *m; 70 int trpoints = ALL_POINTS; 71 72 (void) setlocale(LC_CTYPE, ""); 73 74 while ((ch = getopt(argc,argv,"f:dlm:nRTt:")) != -1) 75 switch((char)ch) { 76 case 'f': 77 tracefile = optarg; 78 break; 79 case 'd': 80 decimal = 1; 81 break; 82 case 'l': 83 tail = 1; 84 break; 85 case 'm': 86 maxdata = atoi(optarg); 87 break; 88 case 'n': 89 fancy = 0; 90 break; 91 case 'R': 92 timestamp = 2; /* relative timestamp */ 93 break; 94 case 'T': 95 timestamp = 1; 96 break; 97 case 't': 98 trpoints = getpoints(optarg); 99 if (trpoints < 0) 100 errx(1, "unknown trace point in %s", optarg); 101 break; 102 default: 103 usage(); 104 } 105 106 if (argc > optind) 107 usage(); 108 109 m = (void *)malloc(size = 1025); 110 if (m == NULL) 111 errx(1, "%s", strerror(ENOMEM)); 112 if (!freopen(tracefile, "r", stdin)) 113 err(1, "%s", tracefile); 114 while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) { 115 if (trpoints & (1<<ktr_header.ktr_type)) 116 dumpheader(&ktr_header); 117 if ((ktrlen = ktr_header.ktr_len) < 0) 118 errx(1, "bogus length 0x%x", ktrlen); 119 if (ktrlen > size) { 120 m = (void *)realloc(m, ktrlen+1); 121 if (m == NULL) 122 errx(1, "%s", strerror(ENOMEM)); 123 size = ktrlen; 124 } 125 if (ktrlen && fread_tail(m, ktrlen, 1) == 0) 126 errx(1, "data too short"); 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); 132 break; 133 case KTR_SYSRET: 134 ktrsysret((struct ktr_sysret *)m); 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); 144 break; 145 case KTR_CSW: 146 ktrcsw((struct ktr_csw *)m); 147 break; 148 case KTR_USER: 149 ktruser(ktrlen, m); 150 break; 151 } 152 if (tail) 153 (void)fflush(stdout); 154 } 155 } 156 157 fread_tail(buf, size, num) 158 char *buf; 159 int num, size; 160 { 161 int i; 162 163 while ((i = fread(buf, size, num, stdin)) == 0 && tail) { 164 (void)sleep(1); 165 clearerr(stdin); 166 } 167 return (i); 168 } 169 170 dumpheader(kth) 171 struct ktr_header *kth; 172 { 173 static char unknown[64]; 174 static struct timeval prevtime, temp; 175 char *type; 176 177 switch (kth->ktr_type) { 178 case KTR_SYSCALL: 179 type = "CALL"; 180 break; 181 case KTR_SYSRET: 182 type = "RET "; 183 break; 184 case KTR_NAMEI: 185 type = "NAMI"; 186 break; 187 case KTR_GENIO: 188 type = "GIO "; 189 break; 190 case KTR_PSIG: 191 type = "PSIG"; 192 break; 193 case KTR_CSW: 194 type = "CSW"; 195 break; 196 case KTR_USER: 197 type = "USER"; 198 break; 199 default: 200 (void)sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type); 201 type = unknown; 202 } 203 204 (void)printf("%6d %-8.*s ", kth->ktr_pid, MAXCOMLEN, kth->ktr_comm); 205 if (timestamp) { 206 if (timestamp == 2) { 207 temp = kth->ktr_time; 208 timevalsub(&kth->ktr_time, &prevtime); 209 prevtime = temp; 210 } 211 (void)printf("%ld.%06ld ", 212 kth->ktr_time.tv_sec, kth->ktr_time.tv_usec); 213 } 214 (void)printf("%s ", type); 215 } 216 217 #include <sys/syscall.h> 218 #define KTRACE 219 #include <sys/kern/syscalls.c> 220 #undef KTRACE 221 int nsyscalls = sizeof (syscallnames) / sizeof (syscallnames[0]); 222 223 static char *ptrace_ops[] = { 224 "PT_TRACE_ME", "PT_READ_I", "PT_READ_D", "PT_READ_U", 225 "PT_WRITE_I", "PT_WRITE_D", "PT_WRITE_U", "PT_CONTINUE", 226 "PT_KILL", "PT_STEP", "PT_ATTACH", "PT_DETACH", 227 }; 228 229 ktrsyscall(ktr) 230 register struct ktr_syscall *ktr; 231 { 232 register narg = ktr->ktr_narg; 233 register register_t *ip; 234 char *ioctlname(); 235 236 if (ktr->ktr_code >= nsyscalls || ktr->ktr_code < 0) 237 (void)printf("[%d]", ktr->ktr_code); 238 else 239 (void)printf("%s", syscallnames[ktr->ktr_code]); 240 ip = &ktr->ktr_args[0]; 241 if (narg) { 242 char c = '('; 243 if (fancy) { 244 if (ktr->ktr_code == SYS_ioctl) { 245 char *cp; 246 if (decimal) 247 (void)printf("(%ld", (long)*ip); 248 else 249 (void)printf("(%#lx", (long)*ip); 250 ip++; 251 narg--; 252 if ((cp = ioctlname(*ip)) != NULL) 253 (void)printf(",%s", cp); 254 else { 255 if (decimal) 256 (void)printf(",%ld", (long)*ip); 257 else 258 (void)printf(",%#lx ", (long)*ip); 259 } 260 c = ','; 261 ip++; 262 narg--; 263 } else if (ktr->ktr_code == SYS_ptrace) { 264 if (*ip < sizeof(ptrace_ops) / 265 sizeof(ptrace_ops[0]) && *ip >= 0) 266 (void)printf("(%s", ptrace_ops[*ip]); 267 #ifdef PT_GETREGS 268 else if (*ip == PT_GETREGS) 269 (void)printf("(%s", "PT_GETREGS"); 270 #endif 271 #ifdef PT_SETREGS 272 else if (*ip == PT_SETREGS) 273 (void)printf("(%s", "PT_SETREGS"); 274 #endif 275 #ifdef PT_GETFPREGS 276 else if (*ip == PT_GETFPREGS) 277 (void)printf("(%s", "PT_GETFPREGS"); 278 #endif 279 #ifdef PT_SETFPREGS 280 else if (*ip == PT_SETFPREGS) 281 (void)printf("(%s", "PT_SETFPREGS"); 282 #endif 283 #ifdef PT_GETDBREGS 284 else if (*ip == PT_GETDBREGS) 285 (void)printf("(%s", "PT_GETDBREGS"); 286 #endif 287 #ifdef PT_SETDBREGS 288 else if (*ip == PT_SETDBREGS) 289 (void)printf("(%s", "PT_SETDBREGS"); 290 #endif 291 else 292 (void)printf("(%ld", (long)*ip); 293 c = ','; 294 ip++; 295 narg--; 296 } 297 } 298 while (narg) { 299 if (decimal) 300 (void)printf("%c%ld", c, (long)*ip); 301 else 302 (void)printf("%c%#lx", c, (long)*ip); 303 c = ','; 304 ip++; 305 narg--; 306 } 307 (void)putchar(')'); 308 } 309 (void)putchar('\n'); 310 } 311 312 ktrsysret(ktr) 313 struct ktr_sysret *ktr; 314 { 315 register register_t ret = ktr->ktr_retval; 316 register int error = ktr->ktr_error; 317 register int code = ktr->ktr_code; 318 319 if (code >= nsyscalls || code < 0) 320 (void)printf("[%d] ", code); 321 else 322 (void)printf("%s ", syscallnames[code]); 323 324 if (error == 0) { 325 if (fancy) { 326 (void)printf("%d", ret); 327 if (ret < 0 || ret > 9) 328 (void)printf("/%#lx", (long)ret); 329 } else { 330 if (decimal) 331 (void)printf("%ld", (long)ret); 332 else 333 (void)printf("%#lx", (long)ret); 334 } 335 } else if (error == ERESTART) 336 (void)printf("RESTART"); 337 else if (error == EJUSTRETURN) 338 (void)printf("JUSTRETURN"); 339 else { 340 (void)printf("-1 errno %d", ktr->ktr_error); 341 if (fancy) 342 (void)printf(" %s", strerror(ktr->ktr_error)); 343 } 344 (void)putchar('\n'); 345 } 346 347 ktrnamei(cp, len) 348 char *cp; 349 { 350 (void)printf("\"%.*s\"\n", len, cp); 351 } 352 353 ktrgenio(ktr, len) 354 struct ktr_genio *ktr; 355 { 356 register int datalen = len - sizeof (struct ktr_genio); 357 register char *dp = (char *)ktr + sizeof (struct ktr_genio); 358 register char *cp; 359 register int col = 0; 360 register width; 361 char visbuf[5]; 362 static screenwidth = 0; 363 364 if (screenwidth == 0) { 365 struct winsize ws; 366 367 if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 && 368 ws.ws_col > 8) 369 screenwidth = ws.ws_col; 370 else 371 screenwidth = 80; 372 } 373 printf("fd %d %s %d byte%s\n", ktr->ktr_fd, 374 ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen, 375 datalen == 1 ? "" : "s"); 376 if (maxdata && datalen > maxdata) 377 datalen = maxdata; 378 (void)printf(" \""); 379 col = 8; 380 for (;datalen > 0; datalen--, dp++) { 381 (void) vis(visbuf, *dp, VIS_CSTYLE, *(dp+1)); 382 cp = visbuf; 383 /* 384 * Keep track of printables and 385 * space chars (like fold(1)). 386 */ 387 if (col == 0) { 388 (void)putchar('\t'); 389 col = 8; 390 } 391 switch(*cp) { 392 case '\n': 393 col = 0; 394 (void)putchar('\n'); 395 continue; 396 case '\t': 397 width = 8 - (col&07); 398 break; 399 default: 400 width = strlen(cp); 401 } 402 if (col + width > (screenwidth-2)) { 403 (void)printf("\\\n\t"); 404 col = 8; 405 } 406 col += width; 407 do { 408 (void)putchar(*cp++); 409 } while (*cp); 410 } 411 if (col == 0) 412 (void)printf(" "); 413 (void)printf("\"\n"); 414 } 415 416 char *signames[] = { 417 "NULL", "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT", /* 1 - 6 */ 418 "EMT", "FPE", "KILL", "BUS", "SEGV", "SYS", /* 7 - 12 */ 419 "PIPE", "ALRM", "TERM", "URG", "STOP", "TSTP", /* 13 - 18 */ 420 "CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU", /* 19 - 24 */ 421 "XFSZ", "VTALRM", "PROF", "WINCH", "29", "USR1", /* 25 - 30 */ 422 "USR2", NULL, /* 31 - 32 */ 423 }; 424 425 ktrpsig(psig) 426 struct ktr_psig *psig; 427 { 428 (void)printf("SIG%s ", signames[psig->signo]); 429 if (psig->action == SIG_DFL) 430 (void)printf("SIG_DFL\n"); 431 else 432 (void)printf("caught handler=0x%lx mask=0x%x code=0x%x\n", 433 (u_long)psig->action, psig->mask, psig->code); 434 } 435 436 ktrcsw(cs) 437 struct ktr_csw *cs; 438 { 439 (void)printf("%s %s\n", cs->out ? "stop" : "resume", 440 cs->user ? "user" : "kernel"); 441 } 442 443 ktruser(len, p) 444 int len; 445 unsigned char *p; 446 { 447 (void)printf("%d ", len); 448 while (len--) 449 (void)printf(" %02x", *p++); 450 (void)printf("\n"); 451 452 } 453 454 usage() 455 { 456 (void)fprintf(stderr, 457 "usage: kdump [-dnlRT] [-f trfile] [-m maxdata] [-t [cnisuw]]\n"); 458 exit(1); 459 } 460