Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / usr.bin / kdump / kdump.c
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.2 2003/06/17 04:29:27 dillon Exp $
37  */
38
39 #define _KERNEL
40 extern int errno;
41 #include <sys/errno.h>
42 #undef _KERNEL
43 #include <sys/param.h>
44 #include <sys/errno.h>
45 #include <sys/time.h>
46 #include <sys/uio.h>
47 #include <sys/ktrace.h>
48 #include <sys/ioctl.h>
49 #include <sys/ptrace.h>
50 #include <err.h>
51 #include <locale.h>
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <string.h>
55 #include <unistd.h>
56 #include <vis.h>
57 #include "ktrace.h"
58
59 int timestamp, decimal, fancy = 1, tail, maxdata;
60 char *tracefile = DEF_TRACEFILE;
61 struct ktr_header ktr_header;
62
63 #define eqs(s1, s2)     (strcmp((s1), (s2)) == 0)
64
65 main(argc, argv)
66         int argc;
67         char *argv[];
68 {
69         int ch, ktrlen, size;
70         register void *m;
71         int trpoints = ALL_POINTS;
72
73         (void) setlocale(LC_CTYPE, "");
74
75         while ((ch = getopt(argc,argv,"f:dlm:nRTt:")) != -1)
76                 switch((char)ch) {
77                 case 'f':
78                         tracefile = optarg;
79                         break;
80                 case 'd':
81                         decimal = 1;
82                         break;
83                 case 'l':
84                         tail = 1;
85                         break;
86                 case 'm':
87                         maxdata = atoi(optarg);
88                         break;
89                 case 'n':
90                         fancy = 0;
91                         break;
92                 case 'R':
93                         timestamp = 2;  /* relative timestamp */
94                         break;
95                 case 'T':
96                         timestamp = 1;
97                         break;
98                 case 't':
99                         trpoints = getpoints(optarg);
100                         if (trpoints < 0)
101                                 errx(1, "unknown trace point in %s", optarg);
102                         break;
103                 default:
104                         usage();
105                 }
106
107         if (argc > optind)
108                 usage();
109
110         m = (void *)malloc(size = 1025);
111         if (m == NULL)
112                 errx(1, "%s", strerror(ENOMEM));
113         if (!freopen(tracefile, "r", stdin))
114                 err(1, "%s", tracefile);
115         while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) {
116                 if (trpoints & (1<<ktr_header.ktr_type))
117                         dumpheader(&ktr_header);
118                 if ((ktrlen = ktr_header.ktr_len) < 0)
119                         errx(1, "bogus length 0x%x", ktrlen);
120                 if (ktrlen > size) {
121                         m = (void *)realloc(m, ktrlen+1);
122                         if (m == NULL)
123                                 errx(1, "%s", strerror(ENOMEM));
124                         size = ktrlen;
125                 }
126                 if (ktrlen && fread_tail(m, ktrlen, 1) == 0)
127                         errx(1, "data too short");
128                 if ((trpoints & (1<<ktr_header.ktr_type)) == 0)
129                         continue;
130                 switch (ktr_header.ktr_type) {
131                 case KTR_SYSCALL:
132                         ktrsyscall((struct ktr_syscall *)m);
133                         break;
134                 case KTR_SYSRET:
135                         ktrsysret((struct ktr_sysret *)m);
136                         break;
137                 case KTR_NAMEI:
138                         ktrnamei(m, ktrlen);
139                         break;
140                 case KTR_GENIO:
141                         ktrgenio((struct ktr_genio *)m, ktrlen);
142                         break;
143                 case KTR_PSIG:
144                         ktrpsig((struct ktr_psig *)m);
145                         break;
146                 case KTR_CSW:
147                         ktrcsw((struct ktr_csw *)m);
148                         break;
149                 case KTR_USER:
150                         ktruser(ktrlen, m);
151                         break;
152                 }
153                 if (tail)
154                         (void)fflush(stdout);
155         }
156 }
157
158 fread_tail(buf, size, num)
159         char *buf;
160         int num, size;
161 {
162         int i;
163
164         while ((i = fread(buf, size, num, stdin)) == 0 && tail) {
165                 (void)sleep(1);
166                 clearerr(stdin);
167         }
168         return (i);
169 }
170
171 dumpheader(kth)
172         struct ktr_header *kth;
173 {
174         static char unknown[64];
175         static struct timeval prevtime, temp;
176         char *type;
177
178         switch (kth->ktr_type) {
179         case KTR_SYSCALL:
180                 type = "CALL";
181                 break;
182         case KTR_SYSRET:
183                 type = "RET ";
184                 break;
185         case KTR_NAMEI:
186                 type = "NAMI";
187                 break;
188         case KTR_GENIO:
189                 type = "GIO ";
190                 break;
191         case KTR_PSIG:
192                 type = "PSIG";
193                 break;
194         case KTR_CSW:
195                 type = "CSW";
196                 break;
197         case KTR_USER:
198                 type = "USER";
199                 break;
200         default:
201                 (void)sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type);
202                 type = unknown;
203         }
204
205         (void)printf("%6d %-8.*s ", kth->ktr_pid, MAXCOMLEN, kth->ktr_comm);
206         if (timestamp) {
207                 if (timestamp == 2) {
208                         temp = kth->ktr_time;
209                         timevalsub(&kth->ktr_time, &prevtime);
210                         prevtime = temp;
211                 }
212                 (void)printf("%ld.%06ld ",
213                     kth->ktr_time.tv_sec, kth->ktr_time.tv_usec);
214         }
215         (void)printf("%s  ", type);
216 }
217
218 #include <sys/syscall.h>
219 #define KTRACE
220 #include <sys/kern/syscalls.c>
221 #undef KTRACE
222 int nsyscalls = sizeof (syscallnames) / sizeof (syscallnames[0]);
223
224 static char *ptrace_ops[] = {
225         "PT_TRACE_ME",  "PT_READ_I",    "PT_READ_D",    "PT_READ_U",
226         "PT_WRITE_I",   "PT_WRITE_D",   "PT_WRITE_U",   "PT_CONTINUE",
227         "PT_KILL",      "PT_STEP",      "PT_ATTACH",    "PT_DETACH",
228 };
229
230 ktrsyscall(ktr)
231         register struct ktr_syscall *ktr;
232 {
233         register narg = ktr->ktr_narg;
234         register register_t *ip;
235         char *ioctlname();
236
237         if (ktr->ktr_code >= nsyscalls || ktr->ktr_code < 0)
238                 (void)printf("[%d]", ktr->ktr_code);
239         else
240                 (void)printf("%s", syscallnames[ktr->ktr_code]);
241         ip = &ktr->ktr_args[0];
242         if (narg) {
243                 char c = '(';
244                 if (fancy) {
245                         if (ktr->ktr_code == SYS_ioctl) {
246                                 char *cp;
247                                 if (decimal)
248                                         (void)printf("(%ld", (long)*ip);
249                                 else
250                                         (void)printf("(%#lx", (long)*ip);
251                                 ip++;
252                                 narg--;
253                                 if ((cp = ioctlname(*ip)) != NULL)
254                                         (void)printf(",%s", cp);
255                                 else {
256                                         if (decimal)
257                                                 (void)printf(",%ld", (long)*ip);
258                                         else
259                                                 (void)printf(",%#lx ", (long)*ip);
260                                 }
261                                 c = ',';
262                                 ip++;
263                                 narg--;
264                         } else if (ktr->ktr_code == SYS_ptrace) {
265                                 if (*ip < sizeof(ptrace_ops) /
266                                     sizeof(ptrace_ops[0]) && *ip >= 0)
267                                         (void)printf("(%s", ptrace_ops[*ip]);
268 #ifdef PT_GETREGS
269                                 else if (*ip == PT_GETREGS)
270                                         (void)printf("(%s", "PT_GETREGS");
271 #endif
272 #ifdef PT_SETREGS
273                                 else if (*ip == PT_SETREGS)
274                                         (void)printf("(%s", "PT_SETREGS");
275 #endif
276 #ifdef PT_GETFPREGS
277                                 else if (*ip == PT_GETFPREGS)
278                                         (void)printf("(%s", "PT_GETFPREGS");
279 #endif
280 #ifdef PT_SETFPREGS
281                                 else if (*ip == PT_SETFPREGS)
282                                         (void)printf("(%s", "PT_SETFPREGS");
283 #endif
284 #ifdef PT_GETDBREGS
285                                 else if (*ip == PT_GETDBREGS)
286                                         (void)printf("(%s", "PT_GETDBREGS");
287 #endif
288 #ifdef PT_SETDBREGS
289                                 else if (*ip == PT_SETDBREGS)
290                                         (void)printf("(%s", "PT_SETDBREGS");
291 #endif
292                                 else
293                                         (void)printf("(%ld", (long)*ip);
294                                 c = ',';
295                                 ip++;
296                                 narg--;
297                         }
298                 }
299                 while (narg) {
300                         if (decimal)
301                                 (void)printf("%c%ld", c, (long)*ip);
302                         else
303                                 (void)printf("%c%#lx", c, (long)*ip);
304                         c = ',';
305                         ip++;
306                         narg--;
307                 }
308                 (void)putchar(')');
309         }
310         (void)putchar('\n');
311 }
312
313 ktrsysret(ktr)
314         struct ktr_sysret *ktr;
315 {
316         register register_t ret = ktr->ktr_retval;
317         register int error = ktr->ktr_error;
318         register int code = ktr->ktr_code;
319
320         if (code >= nsyscalls || code < 0)
321                 (void)printf("[%d] ", code);
322         else
323                 (void)printf("%s ", syscallnames[code]);
324
325         if (error == 0) {
326                 if (fancy) {
327                         (void)printf("%d", ret);
328                         if (ret < 0 || ret > 9)
329                                 (void)printf("/%#lx", (long)ret);
330                 } else {
331                         if (decimal)
332                                 (void)printf("%ld", (long)ret);
333                         else
334                                 (void)printf("%#lx", (long)ret);
335                 }
336         } else if (error == ERESTART)
337                 (void)printf("RESTART");
338         else if (error == EJUSTRETURN)
339                 (void)printf("JUSTRETURN");
340         else {
341                 (void)printf("-1 errno %d", ktr->ktr_error);
342                 if (fancy)
343                         (void)printf(" %s", strerror(ktr->ktr_error));
344         }
345         (void)putchar('\n');
346 }
347
348 ktrnamei(cp, len)
349         char *cp;
350 {
351         (void)printf("\"%.*s\"\n", len, cp);
352 }
353
354 ktrgenio(ktr, len)
355         struct ktr_genio *ktr;
356 {
357         register int datalen = len - sizeof (struct ktr_genio);
358         register char *dp = (char *)ktr + sizeof (struct ktr_genio);
359         register char *cp;
360         register int col = 0;
361         register width;
362         char visbuf[5];
363         static screenwidth = 0;
364
365         if (screenwidth == 0) {
366                 struct winsize ws;
367
368                 if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 &&
369                     ws.ws_col > 8)
370                         screenwidth = ws.ws_col;
371                 else
372                         screenwidth = 80;
373         }
374         printf("fd %d %s %d byte%s\n", ktr->ktr_fd,
375                 ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen,
376                 datalen == 1 ? "" : "s");
377         if (maxdata && datalen > maxdata)
378                 datalen = maxdata;
379         (void)printf("       \"");
380         col = 8;
381         for (;datalen > 0; datalen--, dp++) {
382                 (void) vis(visbuf, *dp, VIS_CSTYLE, *(dp+1));
383                 cp = visbuf;
384                 /*
385                  * Keep track of printables and
386                  * space chars (like fold(1)).
387                  */
388                 if (col == 0) {
389                         (void)putchar('\t');
390                         col = 8;
391                 }
392                 switch(*cp) {
393                 case '\n':
394                         col = 0;
395                         (void)putchar('\n');
396                         continue;
397                 case '\t':
398                         width = 8 - (col&07);
399                         break;
400                 default:
401                         width = strlen(cp);
402                 }
403                 if (col + width > (screenwidth-2)) {
404                         (void)printf("\\\n\t");
405                         col = 8;
406                 }
407                 col += width;
408                 do {
409                         (void)putchar(*cp++);
410                 } while (*cp);
411         }
412         if (col == 0)
413                 (void)printf("       ");
414         (void)printf("\"\n");
415 }
416
417 char *signames[] = {
418         "NULL", "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT",     /*  1 - 6  */
419         "EMT", "FPE", "KILL", "BUS", "SEGV", "SYS",             /*  7 - 12 */
420         "PIPE", "ALRM",  "TERM", "URG", "STOP", "TSTP",         /* 13 - 18 */
421         "CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU",           /* 19 - 24 */
422         "XFSZ", "VTALRM", "PROF", "WINCH", "29", "USR1",        /* 25 - 30 */
423         "USR2", NULL,                                           /* 31 - 32 */
424 };
425
426 ktrpsig(psig)
427         struct ktr_psig *psig;
428 {
429         (void)printf("SIG%s ", signames[psig->signo]);
430         if (psig->action == SIG_DFL)
431                 (void)printf("SIG_DFL\n");
432         else
433                 (void)printf("caught handler=0x%lx mask=0x%x code=0x%x\n",
434                     (u_long)psig->action, psig->mask, psig->code);
435 }
436
437 ktrcsw(cs)
438         struct ktr_csw *cs;
439 {
440         (void)printf("%s %s\n", cs->out ? "stop" : "resume",
441                 cs->user ? "user" : "kernel");
442 }
443
444 ktruser(len, p)
445         int len;
446         unsigned char *p;
447 {
448         (void)printf("%d ", len);
449         while (len--)
450                 (void)printf(" %02x", *p++);
451         (void)printf("\n");
452                 
453 }
454
455 usage()
456 {
457         (void)fprintf(stderr,
458             "usage: kdump [-dnlRT] [-f trfile] [-m maxdata] [-t [cnisuw]]\n");
459         exit(1);
460 }