kdump.c revision 48852
1169689Skan/*- 2169689Skan * Copyright (c) 1988, 1993 3169689Skan * The Regents of the University of California. All rights reserved. 4169689Skan * 5169689Skan * Redistribution and use in source and binary forms, with or without 6169689Skan * modification, are permitted provided that the following conditions 7169689Skan * are met: 8169689Skan * 1. Redistributions of source code must retain the above copyright 9169689Skan * notice, this list of conditions and the following disclaimer. 10169689Skan * 2. Redistributions in binary form must reproduce the above copyright 11169689Skan * notice, this list of conditions and the following disclaimer in the 12169689Skan * documentation and/or other materials provided with the distribution. 13169689Skan * 3. All advertising materials mentioning features or use of this software 14169689Skan * must display the following acknowledgement: 15169689Skan * This product includes software developed by the University of 16169689Skan * California, Berkeley and its contributors. 17169689Skan * 4. Neither the name of the University nor the names of its contributors 18169689Skan * may be used to endorse or promote products derived from this software 19169689Skan * without specific prior written permission. 20169689Skan * 21169689Skan * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22169689Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23169689Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24169689Skan * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25169689Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26169689Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27169689Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28169689Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29169689Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30169689Skan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31169689Skan * SUCH DAMAGE. 32169689Skan */ 33169689Skan 34169689Skan#ifndef lint 35169689Skanstatic const char copyright[] = 36169689Skan"@(#) Copyright (c) 1988, 1993\n\ 37169689Skan The Regents of the University of California. All rights reserved.\n"; 38169689Skan#endif /* not lint */ 39169689Skan 40169689Skan#ifndef lint 41169689Skan#if 0 42169689Skanstatic char sccsid[] = "@(#)kdump.c 8.1 (Berkeley) 6/6/93"; 43169689Skan#endif 44169689Skanstatic const char rcsid[] = 45169689Skan "$Id: kdump.c,v 1.14 1999/06/26 07:31:13 bde Exp $"; 46169689Skan#endif /* not lint */ 47169689Skan 48169689Skan#define KERNEL 49169689Skanextern int errno; 50169689Skan#include <sys/errno.h> 51169689Skan#undef KERNEL 52169689Skan#include <sys/param.h> 53169689Skan#include <sys/errno.h> 54169689Skan#include <sys/time.h> 55169689Skan#include <sys/uio.h> 56169689Skan#include <sys/ktrace.h> 57169689Skan#include <sys/ioctl.h> 58169689Skan#include <sys/ptrace.h> 59169689Skan#include <err.h> 60169689Skan#include <locale.h> 61169689Skan#include <stdio.h> 62169689Skan#include <stdlib.h> 63169689Skan#include <string.h> 64169689Skan#include <unistd.h> 65169689Skan#include <vis.h> 66169689Skan#include "ktrace.h" 67169689Skan 68169689Skanint timestamp, decimal, fancy = 1, tail, maxdata; 69169689Skanchar *tracefile = DEF_TRACEFILE; 70169689Skanstruct ktr_header ktr_header; 71169689Skan 72169689Skan#define eqs(s1, s2) (strcmp((s1), (s2)) == 0) 73169689Skan 74169689Skanmain(argc, argv) 75169689Skan int argc; 76169689Skan char *argv[]; 77169689Skan{ 78169689Skan int ch, ktrlen, size; 79169689Skan register void *m; 80169689Skan int trpoints = ALL_POINTS; 81169689Skan 82169689Skan (void) setlocale(LC_CTYPE, ""); 83169689Skan 84169689Skan while ((ch = getopt(argc,argv,"f:dlm:nRTt:")) != -1) 85169689Skan switch((char)ch) { 86169689Skan case 'f': 87169689Skan tracefile = optarg; 88169689Skan break; 89169689Skan case 'd': 90169689Skan decimal = 1; 91169689Skan break; 92169689Skan case 'l': 93169689Skan tail = 1; 94169689Skan break; 95169689Skan case 'm': 96169689Skan maxdata = atoi(optarg); 97169689Skan break; 98169689Skan case 'n': 99169689Skan fancy = 0; 100169689Skan break; 101169689Skan case 'R': 102169689Skan timestamp = 2; /* relative timestamp */ 103169689Skan break; 104169689Skan case 'T': 105169689Skan timestamp = 1; 106169689Skan break; 107169689Skan case 't': 108169689Skan trpoints = getpoints(optarg); 109169689Skan if (trpoints < 0) 110169689Skan errx(1, "unknown trace point in %s", optarg); 111169689Skan break; 112169689Skan default: 113169689Skan usage(); 114169689Skan } 115169689Skan 116169689Skan if (argc > optind) 117169689Skan usage(); 118169689Skan 119169689Skan m = (void *)malloc(size = 1025); 120169689Skan if (m == NULL) 121169689Skan errx(1, "%s", strerror(ENOMEM)); 122169689Skan if (!freopen(tracefile, "r", stdin)) 123169689Skan err(1, "%s", tracefile); 124169689Skan while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) { 125169689Skan if (trpoints & (1<<ktr_header.ktr_type)) 126169689Skan dumpheader(&ktr_header); 127169689Skan if ((ktrlen = ktr_header.ktr_len) < 0) 128169689Skan errx(1, "bogus length 0x%x", ktrlen); 129169689Skan if (ktrlen > size) { 130169689Skan m = (void *)realloc(m, ktrlen+1); 131169689Skan if (m == NULL) 132169689Skan errx(1, "%s", strerror(ENOMEM)); 133169689Skan size = ktrlen; 134169689Skan } 135169689Skan if (ktrlen && fread_tail(m, ktrlen, 1) == 0) 136169689Skan errx(1, "data too short"); 137169689Skan if ((trpoints & (1<<ktr_header.ktr_type)) == 0) 138169689Skan continue; 139169689Skan switch (ktr_header.ktr_type) { 140169689Skan case KTR_SYSCALL: 141169689Skan ktrsyscall((struct ktr_syscall *)m); 142169689Skan break; 143169689Skan case KTR_SYSRET: 144169689Skan ktrsysret((struct ktr_sysret *)m); 145169689Skan break; 146169689Skan case KTR_NAMEI: 147169689Skan ktrnamei(m, ktrlen); 148169689Skan break; 149169689Skan case KTR_GENIO: 150169689Skan ktrgenio((struct ktr_genio *)m, ktrlen); 151169689Skan break; 152169689Skan case KTR_PSIG: 153169689Skan ktrpsig((struct ktr_psig *)m); 154169689Skan break; 155169689Skan case KTR_CSW: 156169689Skan ktrcsw((struct ktr_csw *)m); 157169689Skan break; 158169689Skan case KTR_USER: 159169689Skan ktruser(ktrlen, m); 160169689Skan break; 161169689Skan } 162169689Skan if (tail) 163169689Skan (void)fflush(stdout); 164169689Skan } 165169689Skan} 166169689Skan 167169689Skanfread_tail(buf, size, num) 168169689Skan char *buf; 169169689Skan int num, size; 170169689Skan{ 171169689Skan int i; 172169689Skan 173169689Skan while ((i = fread(buf, size, num, stdin)) == 0 && tail) { 174169689Skan (void)sleep(1); 175169689Skan clearerr(stdin); 176169689Skan } 177169689Skan return (i); 178169689Skan} 179169689Skan 180169689Skandumpheader(kth) 181169689Skan struct ktr_header *kth; 182169689Skan{ 183169689Skan static char unknown[64]; 184169689Skan static struct timeval prevtime, temp; 185169689Skan char *type; 186169689Skan 187169689Skan switch (kth->ktr_type) { 188169689Skan case KTR_SYSCALL: 189169689Skan type = "CALL"; 190169689Skan break; 191169689Skan case KTR_SYSRET: 192169689Skan type = "RET "; 193169689Skan break; 194169689Skan case KTR_NAMEI: 195169689Skan type = "NAMI"; 196169689Skan break; 197169689Skan case KTR_GENIO: 198169689Skan type = "GIO "; 199169689Skan break; 200169689Skan case KTR_PSIG: 201169689Skan type = "PSIG"; 202169689Skan break; 203169689Skan case KTR_CSW: 204169689Skan type = "CSW"; 205169689Skan break; 206169689Skan case KTR_USER: 207169689Skan type = "USER"; 208169689Skan break; 209169689Skan default: 210169689Skan (void)sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type); 211169689Skan type = unknown; 212169689Skan } 213169689Skan 214169689Skan (void)printf("%6d %-8.*s ", kth->ktr_pid, MAXCOMLEN, kth->ktr_comm); 215169689Skan if (timestamp) { 216169689Skan if (timestamp == 2) { 217169689Skan temp = kth->ktr_time; 218169689Skan timevalsub(&kth->ktr_time, &prevtime); 219169689Skan prevtime = temp; 220169689Skan } 221169689Skan (void)printf("%ld.%06ld ", 222169689Skan kth->ktr_time.tv_sec, kth->ktr_time.tv_usec); 223169689Skan } 224169689Skan (void)printf("%s ", type); 225169689Skan} 226169689Skan 227169689Skan#include <sys/syscall.h> 228169689Skan#define KTRACE 229169689Skan#include <sys/kern/syscalls.c> 230169689Skan#undef KTRACE 231169689Skanint nsyscalls = sizeof (syscallnames) / sizeof (syscallnames[0]); 232169689Skan 233169689Skanstatic char *ptrace_ops[] = { 234169689Skan "PT_TRACE_ME", "PT_READ_I", "PT_READ_D", "PT_READ_U", 235169689Skan "PT_WRITE_I", "PT_WRITE_D", "PT_WRITE_U", "PT_CONTINUE", 236169689Skan "PT_KILL", "PT_STEP", "PT_ATTACH", "PT_DETACH", 237169689Skan}; 238169689Skan 239169689Skanktrsyscall(ktr) 240169689Skan register struct ktr_syscall *ktr; 241169689Skan{ 242169689Skan register narg = ktr->ktr_narg; 243169689Skan register register_t *ip; 244169689Skan char *ioctlname(); 245169689Skan 246169689Skan if (ktr->ktr_code >= nsyscalls || ktr->ktr_code < 0) 247169689Skan (void)printf("[%d]", ktr->ktr_code); 248169689Skan else 249169689Skan (void)printf("%s", syscallnames[ktr->ktr_code]); 250169689Skan ip = &ktr->ktr_args[0]; 251169689Skan if (narg) { 252169689Skan char c = '('; 253169689Skan if (fancy) { 254169689Skan if (ktr->ktr_code == SYS_ioctl) { 255169689Skan char *cp; 256169689Skan if (decimal) 257169689Skan (void)printf("(%ld", (long)*ip); 258169689Skan else 259169689Skan (void)printf("(%#lx", (long)*ip); 260169689Skan ip++; 261169689Skan narg--; 262169689Skan if ((cp = ioctlname(*ip)) != NULL) 263169689Skan (void)printf(",%s", cp); 264169689Skan else { 265169689Skan if (decimal) 266169689Skan (void)printf(",%ld", (long)*ip); 267169689Skan else 268169689Skan (void)printf(",%#lx ", (long)*ip); 269169689Skan } 270169689Skan c = ','; 271169689Skan ip++; 272169689Skan narg--; 273169689Skan } else if (ktr->ktr_code == SYS_ptrace) { 274169689Skan if (*ip < sizeof(ptrace_ops) / 275169689Skan sizeof(ptrace_ops[0]) && *ip >= 0) 276169689Skan (void)printf("(%s", ptrace_ops[*ip]); 277169689Skan#ifdef PT_GETREGS 278169689Skan else if (*ip == PT_GETREGS) 279169689Skan (void)printf("(%s", "PT_GETREGS"); 280169689Skan#endif 281169689Skan#ifdef PT_SETREGS 282169689Skan else if (*ip == PT_SETREGS) 283169689Skan (void)printf("(%s", "PT_SETREGS"); 284169689Skan#endif 285169689Skan#ifdef PT_GETFPREGS 286169689Skan else if (*ip == PT_GETFPREGS) 287169689Skan (void)printf("(%s", "PT_GETFPREGS"); 288169689Skan#endif 289169689Skan#ifdef PT_SETFPREGS 290169689Skan else if (*ip == PT_SETFPREGS) 291169689Skan (void)printf("(%s", "PT_SETFPREGS"); 292169689Skan#endif 293169689Skan#ifdef PT_GETDBREGS 294169689Skan else if (*ip == PT_GETDBREGS) 295169689Skan (void)printf("(%s", "PT_GETDBREGS"); 296169689Skan#endif 297169689Skan#ifdef PT_SETDBREGS 298169689Skan else if (*ip == PT_SETDBREGS) 299169689Skan (void)printf("(%s", "PT_SETDBREGS"); 300169689Skan#endif 301169689Skan else 302169689Skan (void)printf("(%ld", (long)*ip); 303169689Skan c = ','; 304169689Skan ip++; 305169689Skan narg--; 306169689Skan } 307169689Skan } 308169689Skan while (narg) { 309169689Skan if (decimal) 310169689Skan (void)printf("%c%ld", c, (long)*ip); 311169689Skan else 312169689Skan (void)printf("%c%#lx", c, (long)*ip); 313169689Skan c = ','; 314169689Skan ip++; 315169689Skan narg--; 316169689Skan } 317169689Skan (void)putchar(')'); 318169689Skan } 319169689Skan (void)putchar('\n'); 320169689Skan} 321169689Skan 322169689Skanktrsysret(ktr) 323169689Skan struct ktr_sysret *ktr; 324169689Skan{ 325169689Skan register register_t ret = ktr->ktr_retval; 326169689Skan register int error = ktr->ktr_error; 327169689Skan register int code = ktr->ktr_code; 328169689Skan 329169689Skan if (code >= nsyscalls || code < 0) 330169689Skan (void)printf("[%d] ", code); 331169689Skan else 332169689Skan (void)printf("%s ", syscallnames[code]); 333169689Skan 334169689Skan if (error == 0) { 335169689Skan if (fancy) { 336169689Skan (void)printf("%d", ret); 337169689Skan if (ret < 0 || ret > 9) 338169689Skan (void)printf("/%#lx", (long)ret); 339169689Skan } else { 340169689Skan if (decimal) 341169689Skan (void)printf("%ld", (long)ret); 342169689Skan else 343169689Skan (void)printf("%#lx", (long)ret); 344169689Skan } 345169689Skan } else if (error == ERESTART) 346169689Skan (void)printf("RESTART"); 347169689Skan else if (error == EJUSTRETURN) 348169689Skan (void)printf("JUSTRETURN"); 349169689Skan else { 350169689Skan (void)printf("-1 errno %d", ktr->ktr_error); 351169689Skan if (fancy) 352169689Skan (void)printf(" %s", strerror(ktr->ktr_error)); 353169689Skan } 354169689Skan (void)putchar('\n'); 355169689Skan} 356169689Skan 357169689Skanktrnamei(cp, len) 358169689Skan char *cp; 359169689Skan{ 360169689Skan (void)printf("\"%.*s\"\n", len, cp); 361169689Skan} 362169689Skan 363169689Skanktrgenio(ktr, len) 364169689Skan struct ktr_genio *ktr; 365169689Skan{ 366169689Skan register int datalen = len - sizeof (struct ktr_genio); 367169689Skan register char *dp = (char *)ktr + sizeof (struct ktr_genio); 368169689Skan register char *cp; 369169689Skan register int col = 0; 370169689Skan register width; 371169689Skan char visbuf[5]; 372169689Skan static screenwidth = 0; 373169689Skan 374169689Skan if (screenwidth == 0) { 375169689Skan struct winsize ws; 376169689Skan 377169689Skan if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 && 378169689Skan ws.ws_col > 8) 379169689Skan screenwidth = ws.ws_col; 380169689Skan else 381169689Skan screenwidth = 80; 382169689Skan } 383169689Skan printf("fd %d %s %d byte%s\n", ktr->ktr_fd, 384169689Skan ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen, 385169689Skan datalen == 1 ? "" : "s"); 386169689Skan if (maxdata && datalen > maxdata) 387169689Skan datalen = maxdata; 388169689Skan (void)printf(" \""); 389169689Skan col = 8; 390169689Skan for (;datalen > 0; datalen--, dp++) { 391169689Skan (void) vis(visbuf, *dp, VIS_CSTYLE, *(dp+1)); 392169689Skan cp = visbuf; 393169689Skan /* 394169689Skan * Keep track of printables and 395169689Skan * space chars (like fold(1)). 396169689Skan */ 397169689Skan if (col == 0) { 398169689Skan (void)putchar('\t'); 399169689Skan col = 8; 400169689Skan } 401169689Skan switch(*cp) { 402169689Skan case '\n': 403169689Skan col = 0; 404169689Skan (void)putchar('\n'); 405169689Skan continue; 406169689Skan case '\t': 407169689Skan width = 8 - (col&07); 408169689Skan break; 409169689Skan default: 410169689Skan width = strlen(cp); 411169689Skan } 412169689Skan if (col + width > (screenwidth-2)) { 413169689Skan (void)printf("\\\n\t"); 414169689Skan col = 8; 415169689Skan } 416169689Skan col += width; 417169689Skan do { 418169689Skan (void)putchar(*cp++); 419169689Skan } while (*cp); 420169689Skan } 421169689Skan if (col == 0) 422169689Skan (void)printf(" "); 423169689Skan (void)printf("\"\n"); 424169689Skan} 425169689Skan 426169689Skanchar *signames[] = { 427169689Skan "NULL", "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT", /* 1 - 6 */ 428169689Skan "EMT", "FPE", "KILL", "BUS", "SEGV", "SYS", /* 7 - 12 */ 429169689Skan "PIPE", "ALRM", "TERM", "URG", "STOP", "TSTP", /* 13 - 18 */ 430169689Skan "CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU", /* 19 - 24 */ 431169689Skan "XFSZ", "VTALRM", "PROF", "WINCH", "29", "USR1", /* 25 - 30 */ 432169689Skan "USR2", NULL, /* 31 - 32 */ 433169689Skan}; 434169689Skan 435169689Skanktrpsig(psig) 436169689Skan struct ktr_psig *psig; 437169689Skan{ 438169689Skan (void)printf("SIG%s ", signames[psig->signo]); 439169689Skan if (psig->action == SIG_DFL) 440169689Skan (void)printf("SIG_DFL\n"); 441169689Skan else 442169689Skan (void)printf("caught handler=0x%lx mask=0x%x code=0x%x\n", 443169689Skan (u_long)psig->action, psig->mask, psig->code); 444169689Skan} 445169689Skan 446169689Skanktrcsw(cs) 447169689Skan struct ktr_csw *cs; 448169689Skan{ 449169689Skan (void)printf("%s %s\n", cs->out ? "stop" : "resume", 450169689Skan cs->user ? "user" : "kernel"); 451169689Skan} 452169689Skan 453169689Skanktruser(len, p) 454169689Skan int len; 455169689Skan unsigned char *p; 456169689Skan{ 457169689Skan (void)printf("%d ", len); 458169689Skan while (len--) 459169689Skan (void)printf(" %02x", *p++); 460169689Skan (void)printf("\n"); 461169689Skan 462169689Skan} 463169689Skan 464169689Skanusage() 465169689Skan{ 466169689Skan (void)fprintf(stderr, 467169689Skan "usage: kdump [-dnlRT] [-f trfile] [-m maxdata] [-t [cnisuw]]\n"); 468169689Skan exit(1); 469169689Skan} 470169689Skan