Correct BSD License clause numbering from 1-2-4 to 1-2-3.
[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. Neither the name of the University nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * @(#) Copyright (c) 1988, 1993 The Regents of the University of California.  All rights reserved.
30  * @(#)kdump.c  8.1 (Berkeley) 6/6/93
31  * $FreeBSD: src/usr.bin/kdump/kdump.c,v 1.29 2006/05/20 14:27:22 netchild Exp $
32  */
33
34 #define _KERNEL_STRUCTURES
35
36 #include <sys/errno.h>
37 #include <sys/param.h>
38 #include <sys/time.h>
39 #include <sys/uio.h>
40 #include <sys/ktrace.h>
41 #include <sys/ioctl.h>
42 #include <sys/ptrace.h>
43 #include <dlfcn.h>
44 #include <err.h>
45 #include <locale.h>
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <unistd.h>
50 #include <vis.h>
51 #include "ktrace.h"
52 #include "kdump_subr.h"
53
54 extern const char *ioctlname(u_long);
55
56 static int      dumpheader(struct ktr_header *);
57 static int      fread_tail(void *, int, int);
58 static void     ktrcsw(struct ktr_csw *);
59 static void     ktrgenio(struct ktr_genio *, int);
60 static void     ktrnamei(char *, int);
61 static void     ktrpsig(struct ktr_psig *);
62 static void     ktrsyscall(struct ktr_syscall *);
63 static void     ktrsysret(struct ktr_sysret *);
64 static void     ktruser(int, unsigned char *);
65 static void     ktruser_malloc(int, unsigned char *);
66 static void     ktruser_rtld(int, unsigned char *);
67 static void     timevalfix(struct timeval *);
68 static void     timevalsub(struct timeval *, struct timeval *);
69 static void     usage(void);
70
71 int timestamp, decimal, fancy = 1, tail, maxdata = 64;
72 int fixedformat;
73 int cpustamp;
74 const char *tracefile = DEF_TRACEFILE;
75 struct ktr_header ktr_header;
76
77 #define eqs(s1, s2)     (strcmp((s1), (s2)) == 0)
78
79 int
80 main(int argc, char **argv)
81 {
82         int ch, col, ktrlen, size;
83         pid_t do_pid = -1;
84         void *m;
85         int trpoints = ALL_POINTS;
86         char *cp;
87
88         (void) setlocale(LC_CTYPE, "");
89
90         while ((ch = getopt(argc,argv,"acf:djlm:np:RTt:")) != -1)
91                 switch((char)ch) {
92                 case 'f':
93                         tracefile = optarg;
94                         break;
95                 case 'j':
96                         fixedformat = 1;
97                         break;
98                 case 'c':
99                         cpustamp = 1;
100                         break;
101                 case 'a':
102                         timestamp = 2;  /* relative timestamp */
103                         cpustamp = 1;
104                         break;
105                 case 'd':
106                         decimal = 1;
107                         break;
108                 case 'l':
109                         tail = 1;
110                         break;
111                 case 'm':
112                         maxdata = atoi(optarg);
113                         break;
114                 case 'n':
115                         fancy = 0;
116                         break;
117                 case 'p':
118                         do_pid = strtoul(optarg, &cp, 0);
119                         if (*cp != 0)
120                                 errx(1,"invalid number %s", optarg);
121                         break;
122                 case 'R':
123                         timestamp = 2;  /* relative timestamp */
124                         break;
125                 case 'T':
126                         timestamp = 1;
127                         break;
128                 case 't':
129                         trpoints = getpoints(optarg);
130                         if (trpoints < 0)
131                                 errx(1, "unknown trace point in %s", optarg);
132                         break;
133                 default:
134                         usage();
135                 }
136
137         if (argc > optind)
138                 usage();
139
140         m = (void *)malloc(size = 1025);
141         if (m == NULL)
142                 errx(1, "%s", strerror(ENOMEM));
143         if (!freopen(tracefile, "r", stdin))
144                 err(1, "%s", tracefile);
145         while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) {
146                 if (trpoints & (1 << ktr_header.ktr_type) &&
147                     (do_pid == -1 || ktr_header.ktr_pid == do_pid))
148                         col = dumpheader(&ktr_header);
149                 else
150                         col = -1;
151                 if ((ktrlen = ktr_header.ktr_len) < 0)
152                         errx(1, "bogus length 0x%x", ktrlen);
153                 if (ktrlen > size) {
154                         m = (void *)realloc(m, ktrlen+1);
155                         if (m == NULL)
156                                 errx(1, "%s", strerror(ENOMEM));
157                         size = ktrlen;
158                 }
159                 if (ktrlen && fread_tail(m, ktrlen, 1) == 0)
160                         errx(1, "data too short");
161                 if ((trpoints & (1<<ktr_header.ktr_type)) == 0)
162                         continue;
163                 if (col == -1)
164                         continue;
165                 switch (ktr_header.ktr_type) {
166                 case KTR_SYSCALL:
167                         ktrsyscall((struct ktr_syscall *)m);
168                         break;
169                 case KTR_SYSRET:
170                         ktrsysret((struct ktr_sysret *)m);
171                         break;
172                 case KTR_NAMEI:
173                         ktrnamei(m, ktrlen);
174                         break;
175                 case KTR_GENIO:
176                         ktrgenio((struct ktr_genio *)m, ktrlen);
177                         break;
178                 case KTR_PSIG:
179                         ktrpsig((struct ktr_psig *)m);
180                         break;
181                 case KTR_CSW:
182                         ktrcsw((struct ktr_csw *)m);
183                         break;
184                 case KTR_USER:
185                         ktruser(ktrlen, m);
186                         break;
187                 }
188                 if (tail)
189                         (void)fflush(stdout);
190         }
191         exit(0);
192 }
193
194 static int
195 fread_tail(void *buf, int size, int num)
196 {
197         int i;
198
199         while ((i = fread(buf, size, num, stdin)) == 0 && tail) {
200                 (void)sleep(1);
201                 clearerr(stdin);
202         }
203         return (i);
204 }
205
206 static int
207 dumpheader(struct ktr_header *kth)
208 {
209         static char unknown[64];
210         static struct timeval prevtime, temp;
211         const char *type;
212         int col;
213
214         switch (kth->ktr_type) {
215         case KTR_SYSCALL:
216                 type = "CALL";
217                 break;
218         case KTR_SYSRET:
219                 type = "RET ";
220                 break;
221         case KTR_NAMEI:
222                 type = "NAMI";
223                 break;
224         case KTR_GENIO:
225                 type = "GIO ";
226                 break;
227         case KTR_PSIG:
228                 type = "PSIG";
229                 break;
230         case KTR_CSW:
231                 type = "CSW";
232                 break;
233         case KTR_USER:
234                 type = "USER";
235                 break;
236         default:
237                 (void)sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type);
238                 type = unknown;
239         }
240
241         if (kth->ktr_tid || (kth->ktr_flags & KTRH_THREADED) || fixedformat)
242                 col = printf("%5d:%-4d", kth->ktr_pid, kth->ktr_tid);
243         else
244                 col = printf("%5d", kth->ktr_pid);
245         if (cpustamp)
246                 col += printf(" %2d", KTRH_CPUID_DECODE(kth->ktr_flags));
247         col += printf(" %-8.*s ", MAXCOMLEN, kth->ktr_comm);
248         if (timestamp) {
249                 if (timestamp == 2) {
250                         temp = kth->ktr_time;
251                         timevalsub(&kth->ktr_time, &prevtime);
252                         prevtime = temp;
253                 }
254                 col += printf("%ld.%06ld ",
255                     kth->ktr_time.tv_sec, kth->ktr_time.tv_usec);
256         }
257         col += printf("%s  ", type);
258         return col;
259 }
260
261 #include <sys/syscall.h>
262 #define KTRACE
263 #include <sys/kern/syscalls.c>
264 #undef KTRACE
265 int nsyscalls = sizeof (syscallnames) / sizeof (syscallnames[0]);
266
267 static const char *ptrace_ops[] = {
268         "PT_TRACE_ME",  "PT_READ_I",    "PT_READ_D",    "PT_READ_U",
269         "PT_WRITE_I",   "PT_WRITE_D",   "PT_WRITE_U",   "PT_CONTINUE",
270         "PT_KILL",      "PT_STEP",      "PT_ATTACH",    "PT_DETACH",
271 };
272
273 static void
274 ktrsyscall(struct ktr_syscall *ktr)
275 {
276         int narg = ktr->ktr_narg;
277         register_t *ip;
278
279         if (ktr->ktr_code >= nsyscalls || ktr->ktr_code < 0)
280                 (void)printf("[%d]", ktr->ktr_code);
281         else
282                 (void)printf("%s", syscallnames[ktr->ktr_code]);
283         ip = &ktr->ktr_args[0];
284         if (narg) {
285                 char c = '(';
286                 if (fancy) {
287
288 #define print_number(i,n,c) do {                      \
289         if (decimal)                                  \
290                 (void)printf("%c%ld", c, (long)*i);   \
291         else                                          \
292                 (void)printf("%c%#lx", c, (long)*i);  \
293         i++;                                          \
294         n--;                                          \
295         c = ',';                                      \
296         } while (0);
297
298                         if (ktr->ktr_code == SYS_ioctl) {
299                                 const char *cp;
300                                 print_number(ip,narg,c);
301                                 if ((cp = ioctlname(*ip)) != NULL)
302                                         (void)printf(",%s", cp);
303                                 else {
304                                         if (decimal)
305                                                 (void)printf(",%ld", (long)*ip);
306                                         else
307                                                 (void)printf(",%#lx ", (long)*ip);
308                                 }
309                                 c = ',';
310                                 ip++;
311                                 narg--;
312                         } else if (ktr->ktr_code == SYS_access) {
313                                 print_number(ip,narg,c);
314                                 (void)putchar(',');
315                                 accessmodename ((int)*ip);
316                                 ip++;
317                                 narg--;
318                         } else if (ktr->ktr_code == SYS_open ||
319                                    ktr->ktr_code == SYS_mq_open) {
320                                 int     flags;
321                                 int     mode;
322                                 print_number(ip,narg,c);
323                                 flags = *ip;
324                                 mode = *++ip;
325                                 (void)putchar(',');
326                                 flagsandmodename (flags, mode, decimal);
327                                 ip++;
328                                 narg-=2;
329                         } else if (ktr->ktr_code == SYS_wait4) {
330                                 print_number(ip,narg,c);
331                                 print_number(ip,narg,c);
332                                 (void)putchar(',');
333                                 wait4optname ((int)*ip);
334                                 ip++;
335                                 narg--;
336                         } else if (ktr->ktr_code == SYS_chmod ||
337                                    ktr->ktr_code == SYS_fchmod ||
338                                    ktr->ktr_code == SYS_lchmod) {
339                                 print_number(ip,narg,c);
340                                 (void)putchar(',');
341                                 modename ((int)*ip);
342                                 ip++;
343                                 narg--;
344                         } else if (ktr->ktr_code == SYS_mknod) {
345                                 print_number(ip,narg,c);
346                                 (void)putchar(',');
347                                 modename ((int)*ip);
348                                 ip++;
349                                 narg--;
350                         } else if (ktr->ktr_code == SYS_getfsstat) {
351                                 print_number(ip,narg,c);
352                                 print_number(ip,narg,c);
353                                 (void)putchar(',');
354                                 getfsstatflagsname ((int)*ip);
355                                 ip++;
356                                 narg--;
357                         } else if (ktr->ktr_code == SYS_mount) {
358                                 print_number(ip,narg,c);
359                                 print_number(ip,narg,c);
360                                 (void)putchar(',');
361                                 mountflagsname ((int)*ip);
362                                 ip++;
363                                 narg--;
364                         } else if (ktr->ktr_code == SYS_unmount) {
365                                 print_number(ip,narg,c);
366                                 (void)putchar(',');
367                                 mountflagsname ((int)*ip);
368                                 ip++;
369                                 narg--;
370                         } else if (ktr->ktr_code == SYS_recvmsg ||
371                                    ktr->ktr_code == SYS_sendmsg) {
372                                 print_number(ip,narg,c);
373                                 print_number(ip,narg,c);
374                                 (void)putchar(',');
375                                 sendrecvflagsname ((int)*ip);
376                                 ip++;
377                                 narg--;
378                         } else if (ktr->ktr_code == SYS_recvfrom ||
379                                    ktr->ktr_code == SYS_sendto) {
380                                 print_number(ip,narg,c);
381                                 print_number(ip,narg,c);
382                                 print_number(ip,narg,c);
383                                 (void)putchar(',');
384                                 sendrecvflagsname ((int)*ip);
385                                 ip++;
386                                 narg--;
387                         } else if (ktr->ktr_code == SYS_chflags ||
388                                    ktr->ktr_code == SYS_fchflags) {
389                                 print_number(ip,narg,c);
390                                 (void)putchar(',');
391                                 modename((int)*ip);
392                                 ip++;
393                                 narg--;
394                         } else if (ktr->ktr_code == SYS_kill) {
395                                 print_number(ip,narg,c);
396                                 (void)putchar(',');
397                                 signame((int)*ip);
398                                 ip++;
399                                 narg--;
400                         } else if (ktr->ktr_code == SYS_reboot) {
401                                 (void)putchar('(');
402                                 rebootoptname((int)*ip);
403                                 ip++;
404                                 narg--;
405                         } else if (ktr->ktr_code == SYS_umask) {
406                                 (void)putchar('(');
407                                 modename((int)*ip);
408                                 ip++;
409                                 narg--;
410                         } else if (ktr->ktr_code == SYS_msync) {
411                                 print_number(ip,narg,c);
412                                 print_number(ip,narg,c);
413                                 (void)putchar(',');
414                                 msyncflagsname((int)*ip);
415                                 ip++;
416                                 narg--;
417                         } else if (ktr->ktr_code == SYS_mmap) {
418                                 print_number(ip,narg,c);
419                                 print_number(ip,narg,c);
420                                 (void)putchar(',');
421                                 mmapprotname ((int)*ip);
422                                 (void)putchar(',');
423                                 ip++;
424                                 narg--;
425                                 mmapflagsname ((int)*ip);
426                                 ip++;
427                                 narg--;
428                         } else if (ktr->ktr_code == SYS_mprotect) {
429                                 print_number(ip,narg,c);
430                                 print_number(ip,narg,c);
431                                 (void)putchar(',');
432                                 mmapprotname ((int)*ip);
433                                 ip++;
434                                 narg--;
435                         } else if (ktr->ktr_code == SYS_madvise) {
436                                 print_number(ip,narg,c);
437                                 print_number(ip,narg,c);
438                                 (void)putchar(',');
439                                 madvisebehavname((int)*ip);
440                                 ip++;
441                                 narg--;
442                         } else if (ktr->ktr_code == SYS_setpriority) {
443                                 (void)putchar('(');
444                                 prioname((int)*ip);
445                                 ip++;
446                                 narg--;
447                                 c = ',';
448                                 print_number(ip,narg,c);
449                                 print_number(ip,narg,c);
450                         } else if (ktr->ktr_code == SYS_fcntl) {
451                                 int cmd;
452                                 int arg;
453                                 print_number(ip,narg,c);
454                                 cmd = *ip;
455                                 arg = *++ip;
456                                 (void)putchar(',');
457                                 fcntlcmdname(cmd, arg, decimal);
458                                 ip++;
459                                 narg-=2;
460                         } else if (ktr->ktr_code == SYS_socket) {
461                                 (void)putchar('(');
462                                 sockdomainname((int)*ip);
463                                 ip++;
464                                 narg--;
465                                 (void)putchar(',');
466                                 socktypename((int)*ip);
467                                 ip++;
468                                 narg--;
469                                 c = ',';
470                         } else if (ktr->ktr_code == SYS_setsockopt ||
471                                    ktr->ktr_code == SYS_getsockopt) {
472                                 print_number(ip,narg,c);
473                                 (void)putchar(',');
474                                 sockoptlevelname((int)*ip, decimal);
475                                 ip++;
476                                 narg--;
477                                 (void)putchar(',');
478                                 sockoptname((int)*ip);
479                                 ip++;
480                                 narg--;
481                         } else if (ktr->ktr_code == SYS_lseek) {
482                                 print_number(ip,narg,c);
483                                 /* Hidden 'pad' argument, not in lseek(2) */
484                                 print_number(ip,narg,c);
485                                 print_number(ip,narg,c);
486                                 (void)putchar(',');
487                                 whencename ((int)*ip);
488                                 ip++;
489                                 narg--;
490                         } else if (ktr->ktr_code == SYS_flock) {
491                                 print_number(ip,narg,c);
492                                 (void)putchar(',');
493                                 flockname((int)*ip);
494                                 ip++;
495                                 narg--;
496                         } else if (ktr->ktr_code == SYS_mkfifo ||
497                                    ktr->ktr_code == SYS_mkdir) {
498                                 print_number(ip,narg,c);
499                                 (void)putchar(',');
500                                 modename((int)*ip);
501                                 ip++;
502                                 narg--;
503                         } else if (ktr->ktr_code == SYS_shutdown) {
504                                 print_number(ip,narg,c);
505                                 (void)putchar(',');
506                                 shutdownhowname((int)*ip);
507                                 ip++;
508                                 narg--;
509                         } else if (ktr->ktr_code == SYS_socketpair) {
510                                 (void)putchar('(');
511                                 sockdomainname((int)*ip);
512                                 ip++;
513                                 narg--;
514                                 (void)putchar(',');
515                                 socktypename((int)*ip);
516                                 ip++;
517                                 narg--;
518                                 c = ',';
519                         } else if (ktr->ktr_code == SYS_getrlimit ||
520                                    ktr->ktr_code == SYS_setrlimit) {
521                                 (void)putchar('(');
522                                 rlimitname((int)*ip);
523                                 ip++;
524                                 narg--;
525                                 c = ',';
526                         } else if (ktr->ktr_code == SYS_quotactl) {
527                                 print_number(ip,narg,c);
528                                 quotactlname((int)*ip);
529                                 ip++;
530                                 narg--;
531                                 c = ',';
532                         } else if (ktr->ktr_code == SYS_rtprio) {
533                                 (void)putchar('(');
534                                 rtprioname((int)*ip);
535                                 ip++;
536                                 narg--;
537                                 c = ',';
538                         } else if (ktr->ktr_code == SYS___semctl) {
539                                 print_number(ip,narg,c);
540                                 print_number(ip,narg,c);
541                                 semctlname((int)*ip);
542                                 ip++;
543                                 narg--;
544                         } else if (ktr->ktr_code == SYS_semget) {
545                                 print_number(ip,narg,c);
546                                 print_number(ip,narg,c);
547                                 semgetname((int)*ip);
548                                 ip++;
549                                 narg--;
550                         } else if (ktr->ktr_code == SYS_msgctl) {
551                                 print_number(ip,narg,c);
552                                 shmctlname((int)*ip);
553                                 ip++;
554                                 narg--;
555                         } else if (ktr->ktr_code == SYS_shmat) {
556                                 print_number(ip,narg,c);
557                                 print_number(ip,narg,c);
558                                 shmatname((int)*ip);
559                                 ip++;
560                                 narg--;
561                         } else if (ktr->ktr_code == SYS_shmctl) {
562                                 print_number(ip,narg,c);
563                                 shmctlname((int)*ip);
564                                 ip++;
565                                 narg--;
566                         } else if (ktr->ktr_code == SYS_minherit) {
567                                 print_number(ip,narg,c);
568                                 print_number(ip,narg,c);
569                                 minheritname((int)*ip);
570                                 ip++;
571                                 narg--;
572                         } else if (ktr->ktr_code == SYS_rfork) {
573                                 (void)putchar('(');
574                                 rforkname((int)*ip);
575                                 ip++;
576                                 narg--;
577                                 c = ',';
578                         } else if (ktr->ktr_code == SYS_lio_listio) {
579                                 (void)putchar('(');
580                                 lio_listioname((int)*ip);
581                                 ip++;
582                                 narg--;
583                                 c = ',';
584                         } else if (ktr->ktr_code == SYS_mlockall) {
585                                 (void)putchar('(');
586                                 mlockallname((int)*ip);
587                                 ip++;
588                                 narg--;
589                         } else if (ktr->ktr_code == SYS_sched_setscheduler) {
590                                 print_number(ip,narg,c);
591                                 schedpolicyname((int)*ip);
592                                 ip++;
593                                 narg--;
594                         } else if (ktr->ktr_code == SYS_sched_get_priority_max ||
595                                    ktr->ktr_code == SYS_sched_get_priority_min) {
596                                 (void)putchar('(');
597                                 schedpolicyname((int)*ip);
598                                 ip++;
599                                 narg--;
600                         } else if (ktr->ktr_code == SYS_sendfile) {
601                                 print_number(ip,narg,c);
602                                 print_number(ip,narg,c);
603                                 print_number(ip,narg,c);
604                                 print_number(ip,narg,c);
605                                 print_number(ip,narg,c);
606                                 print_number(ip,narg,c);
607                                 sendfileflagsname((int)*ip);
608                                 ip++;
609                                 narg--;
610                         } else if (ktr->ktr_code == SYS_kldsym) {
611                                 print_number(ip,narg,c);
612                                 kldsymcmdname((int)*ip);
613                                 ip++;
614                                 narg--;
615                         } else if (ktr->ktr_code == SYS_sigprocmask) {
616                                 (void)putchar('(');
617                                 sigprocmaskhowname((int)*ip);
618                                 ip++;
619                                 narg--;
620                                 c = ',';
621                         } else if (ktr->ktr_code == SYS___acl_get_file ||
622                                    ktr->ktr_code == SYS___acl_set_file ||
623                                    ktr->ktr_code == SYS___acl_get_fd ||
624                                    ktr->ktr_code == SYS___acl_set_fd ||
625                                    ktr->ktr_code == SYS___acl_delete_file ||
626                                    ktr->ktr_code == SYS___acl_delete_fd ||
627                                    ktr->ktr_code == SYS___acl_aclcheck_file ||
628                                    ktr->ktr_code == SYS___acl_aclcheck_fd) {
629                                 print_number(ip,narg,c);
630                                 acltypename((int)*ip);
631                                 ip++;
632                                 narg--;
633                         } else if (ktr->ktr_code == SYS_sigaction) {
634                                 (void)putchar('(');
635                                 signame((int)*ip);
636                                 ip++;
637                                 narg--;
638                                 c = ',';
639                         } else if (ktr->ktr_code == SYS_extattrctl) {
640                                 print_number(ip,narg,c);
641                                 extattrctlname((int)*ip);
642                                 ip++;
643                                 narg--;
644                         } else if (ktr->ktr_code == SYS_ptrace) {
645                                 if (*ip < (register_t)(sizeof(ptrace_ops) /
646                                     sizeof(ptrace_ops[0])) && *ip >= 0)
647                                         (void)printf("(%s", ptrace_ops[*ip]);
648 #ifdef PT_GETREGS
649                                 else if (*ip == PT_GETREGS)
650                                         (void)printf("(%s", "PT_GETREGS");
651 #endif
652 #ifdef PT_SETREGS
653                                 else if (*ip == PT_SETREGS)
654                                         (void)printf("(%s", "PT_SETREGS");
655 #endif
656 #ifdef PT_GETFPREGS
657                                 else if (*ip == PT_GETFPREGS)
658                                         (void)printf("(%s", "PT_GETFPREGS");
659 #endif
660 #ifdef PT_SETFPREGS
661                                 else if (*ip == PT_SETFPREGS)
662                                         (void)printf("(%s", "PT_SETFPREGS");
663 #endif
664 #ifdef PT_GETDBREGS
665                                 else if (*ip == PT_GETDBREGS)
666                                         (void)printf("(%s", "PT_GETDBREGS");
667 #endif
668 #ifdef PT_SETDBREGS
669                                 else if (*ip == PT_SETDBREGS)
670                                         (void)printf("(%s", "PT_SETDBREGS");
671 #endif
672                                 else
673                                         (void)printf("(%ld", (long)*ip);
674                                 c = ',';
675                                 ip++;
676                                 narg--;
677                         }
678                 }
679                 while (narg > 0) {
680                         print_number(ip,narg,c);
681                 }
682                 (void)putchar(')');
683         }
684         (void)putchar('\n');
685 }
686
687 static void
688 ktrsysret(struct ktr_sysret *ktr)
689 {
690         register_t ret = ktr->ktr_retval;
691         int error = ktr->ktr_error;
692         int code = ktr->ktr_code;
693
694         if (code >= nsyscalls || code < 0)
695                 (void)printf("[%d] ", code);
696         else
697                 (void)printf("%s ", syscallnames[code]);
698
699         if (error == 0) {
700                 if (fancy) {
701                         (void)printf("%ld", (long)ret);
702                         if (ret < 0 || ret > 9)
703                                 (void)printf("/%#lx", (long)ret);
704                 } else {
705                         if (decimal)
706                                 (void)printf("%ld", (long)ret);
707                         else
708                                 (void)printf("%#lx", (long)ret);
709                 }
710         } else if (error == ERESTART)
711                 (void)printf("RESTART");
712         else if (error == EJUSTRETURN)
713                 (void)printf("JUSTRETURN");
714         else {
715                 (void)printf("-1 errno %d", ktr->ktr_error);
716                 if (fancy)
717                         (void)printf(" %s", strerror(ktr->ktr_error));
718         }
719         (void)putchar('\n');
720 }
721
722 static void
723 ktrnamei(char *cp, int len)
724 {
725         (void)printf("\"%.*s\"\n", len, cp);
726 }
727
728 static void
729 ktrgenio(struct ktr_genio *ktr, int len)
730 {
731         int datalen = len - sizeof (struct ktr_genio);
732         char *dp = (char *)ktr + sizeof (struct ktr_genio);
733         char *cp;
734         int col = 0;
735         int width;
736         char visbuf[5];
737         static int screenwidth = 0;
738
739         if (screenwidth == 0) {
740                 struct winsize ws;
741
742                 if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 &&
743                     ws.ws_col > 8)
744                         screenwidth = ws.ws_col;
745                 else
746                         screenwidth = 80;
747         }
748         printf("fd %d %s %d byte%s\n", ktr->ktr_fd,
749                 ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen,
750                 datalen == 1 ? "" : "s");
751         if (maxdata && datalen > maxdata)
752                 datalen = maxdata;
753         (void)printf("       \"");
754         col = 8;
755         for (;datalen > 0; datalen--, dp++) {
756                 (void) vis(visbuf, *dp, VIS_CSTYLE, *(dp+1));
757                 cp = visbuf;
758                 /*
759                  * Keep track of printables and
760                  * space chars (like fold(1)).
761                  */
762                 if (col == 0) {
763                         (void)putchar('\t');
764                         col = 8;
765                 }
766                 switch(*cp) {
767                 case '\n':
768                         col = 0;
769                         (void)putchar('\n');
770                         continue;
771                 case '\t':
772                         width = 8 - (col&07);
773                         break;
774                 default:
775                         width = strlen(cp);
776                 }
777                 if (col + width > (screenwidth-2)) {
778                         (void)printf("\\\n\t");
779                         col = 8;
780                 }
781                 col += width;
782                 do {
783                         (void)putchar(*cp++);
784                 } while (*cp);
785         }
786         if (col == 0)
787                 (void)printf("       ");
788         (void)printf("\"\n");
789 }
790
791 const char *signames[NSIG] = {
792         "NULL", "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT",     /*  1 - 6  */
793         "EMT", "FPE", "KILL", "BUS", "SEGV", "SYS",             /*  7 - 12 */
794         "PIPE", "ALRM",  "TERM", "URG", "STOP", "TSTP",         /* 13 - 18 */
795         "CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU",           /* 19 - 24 */
796         "XFSZ", "VTALRM", "PROF", "WINCH", "29", "USR1",        /* 25 - 30 */
797         "USR2", NULL,                                           /* 31 - 32 */
798 };
799
800 static void
801 ktrpsig(struct ktr_psig *psig)
802 {
803         (void)printf("SIG%s ", signames[psig->signo]);
804         if (psig->action == SIG_DFL)
805                 (void)printf("SIG_DFL\n");
806         else
807                 (void)printf("caught handler=0x%lx mask=0x%x code=0x%x\n",
808                     (u_long)psig->action, psig->mask.__bits[0], psig->code);
809 }
810
811 static void
812 ktrcsw(struct ktr_csw *cs)
813 {
814         (void)printf("%s %s\n", cs->out ? "stop" : "resume",
815                 cs->user ? "user" : "kernel");
816 }
817
818 #define UTRACE_DLOPEN_START             1
819 #define UTRACE_DLOPEN_STOP              2
820 #define UTRACE_DLCLOSE_START            3
821 #define UTRACE_DLCLOSE_STOP             4
822 #define UTRACE_LOAD_OBJECT              5
823 #define UTRACE_UNLOAD_OBJECT            6
824 #define UTRACE_ADD_RUNDEP               7
825 #define UTRACE_PRELOAD_FINISHED         8
826 #define UTRACE_INIT_CALL                9
827 #define UTRACE_FINI_CALL                10
828
829 struct utrace_rtld {
830         char sig[4];                            /* 'RTLD' */
831         int event;
832         void *handle;
833         void *mapbase;
834         size_t mapsize;
835         int refcnt;
836         char name[MAXPATHLEN];
837 };
838
839 static void
840 ktruser_rtld(int len, unsigned char *p)
841 {
842         struct utrace_rtld *ut = (struct utrace_rtld *)p;
843         void *parent;
844         int mode;
845
846         switch (ut->event) {
847         case UTRACE_DLOPEN_START:
848                 mode = ut->refcnt;
849                 printf("dlopen(%s, ", ut->name);
850                 switch (mode & RTLD_MODEMASK) {
851                 case RTLD_NOW:
852                         printf("RTLD_NOW");
853                         break;
854                 case RTLD_LAZY:
855                         printf("RTLD_LAZY");
856                         break;
857                 default:
858                         printf("%#x", mode & RTLD_MODEMASK);
859                 }
860                 if (mode & RTLD_GLOBAL)
861                         printf(" | RTLD_GLOBAL");
862                 if (mode & RTLD_TRACE)
863                         printf(" | RTLD_TRACE");
864                 if (mode & ~(RTLD_MODEMASK | RTLD_GLOBAL | RTLD_TRACE))
865                         printf(" | %#x", mode &
866                             ~(RTLD_MODEMASK | RTLD_GLOBAL | RTLD_TRACE));
867                 printf(")\n");
868                 break;
869         case UTRACE_DLOPEN_STOP:
870                 printf("%p = dlopen(%s) ref %d\n", ut->handle, ut->name,
871                     ut->refcnt);
872                 break;
873         case UTRACE_DLCLOSE_START:
874                 printf("dlclose(%p) (%s, %d)\n", ut->handle, ut->name,
875                     ut->refcnt);
876                 break;
877         case UTRACE_DLCLOSE_STOP:
878                 printf("dlclose(%p) finished\n", ut->handle);
879                 break;
880         case UTRACE_LOAD_OBJECT:
881                 printf("RTLD: loaded   %p @ %p - %p (%s)\n", ut->handle,
882                     ut->mapbase, (char *)ut->mapbase + ut->mapsize - 1,
883                     ut->name);
884                 break;
885         case UTRACE_UNLOAD_OBJECT:
886                 printf("RTLD: unloaded %p @ %p - %p (%s)\n", ut->handle,
887                     ut->mapbase, (char *)ut->mapbase + ut->mapsize - 1,
888                     ut->name);
889                 break;
890         case UTRACE_ADD_RUNDEP:
891                 parent = ut->mapbase;
892                 printf("RTLD: %p now depends on %p (%s, %d)\n", parent,
893                     ut->handle, ut->name, ut->refcnt);
894                 break;
895         case UTRACE_PRELOAD_FINISHED:
896                 printf("RTLD: LD_PRELOAD finished\n");
897                 break;
898         case UTRACE_INIT_CALL:
899                 printf("RTLD: init %p for %p (%s)\n", ut->mapbase, ut->handle,
900                     ut->name);
901                 break;
902         case UTRACE_FINI_CALL:
903                 printf("RTLD: fini %p for %p (%s)\n", ut->mapbase, ut->handle,
904                     ut->name);
905                 break;
906         default:
907                 p += 4;
908                 len -= 4;
909                 printf("RTLD: %d ", len);
910                 while (len--)
911                         if (decimal)
912                                 printf(" %d", *p++);
913                         else
914                                 printf(" %02x", *p++);
915                 printf("\n");
916         }
917 }
918
919 struct utrace_malloc {
920         void *p;
921         size_t s;
922         void *r;
923 };
924
925 static void
926 ktruser_malloc(int len __unused, unsigned char *p)
927 {
928         struct utrace_malloc *ut = (struct utrace_malloc *)p;
929
930         if (ut->p == NULL) {
931                 if (ut->s == 0 && ut->r == NULL)
932                         printf("malloc_init()\n");
933                 else
934                         printf("%p = malloc(%zu)\n", ut->r, ut->s);
935         } else {
936                 if (ut->s == 0)
937                         printf("free(%p)\n", ut->p);
938                 else
939                         printf("%p = realloc(%p, %zu)\n", ut->r, ut->p, ut->s);
940         }
941 }
942
943 static void
944 ktruser(int len, unsigned char *p)
945 {
946
947         if (len >= 8 && bcmp(p, "RTLD", 4) == 0) {
948                 ktruser_rtld(len, p);
949                 return;
950         }
951
952         if (len == sizeof(struct utrace_malloc)) {
953                 ktruser_malloc(len, p);
954                 return;
955         }
956
957         (void)printf("%d ", len);
958         while (len--)
959                 (void)printf(" %02x", *p++);
960         (void)printf("\n");
961 }
962
963 static void
964 usage(void)
965 {
966         (void)fprintf(stderr,
967             "usage: kdump [-dnlRT] [-f trfile] [-m maxdata] [-t [cnisuw]] [-p pid]\n");
968         exit(1);
969 }
970
971 static void
972 timevalsub(struct timeval *t1, struct timeval *t2)
973 {
974         t1->tv_sec -= t2->tv_sec;
975         t1->tv_usec -= t2->tv_usec;
976         timevalfix(t1);
977 }
978
979 static void
980 timevalfix(struct timeval *t1)
981 {
982         if (t1->tv_usec < 0) {
983                 t1->tv_sec--;
984                 t1->tv_usec += 1000000;
985         }
986         if (t1->tv_usec >= 1000000) {
987                 t1->tv_sec++;
988                 t1->tv_usec -= 1000000;
989         }
990 }