nrelease - fix/improve livecd
[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/ktrace.h>
40 #include <sys/ioctl.h>
41 #include <sys/ptrace.h>
42 #include <dlfcn.h>
43 #include <err.h>
44 #include <locale.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <unistd.h>
49 #include <vis.h>
50 #include "ktrace.h"
51 #include "kdump_subr.h"
52
53 extern const char *ioctlname(u_long);
54
55 static int      dumpheader(struct ktr_header *);
56 static int      fread_tail(void *, int, int);
57 static void     ktrcsw(struct ktr_csw *);
58 static void     ktrgenio(struct ktr_genio *, int);
59 static void     ktrnamei(char *, int);
60 static void     ktrpsig(struct ktr_psig *);
61 static void     ktrsyscall(struct ktr_syscall *);
62 static void     ktrsysret(struct ktr_sysret *);
63 static void     ktruser(int, unsigned char *);
64 static void     ktruser_malloc(int, unsigned char *);
65 static void     ktruser_rtld(int, unsigned char *);
66 static void     timevalfix(struct timeval *);
67 static void     timevalsub(struct timeval *, struct timeval *);
68 static void     usage(void);
69
70 int timestamp, decimal, fancy = 1, tail, maxdata = 64;
71 int fixedformat;
72 int cpustamp;
73 const char *tracefile = DEF_TRACEFILE;
74 struct ktr_header ktr_header;
75
76 #define eqs(s1, s2)     (strcmp((s1), (s2)) == 0)
77
78 int
79 main(int argc, char **argv)
80 {
81         int ch, col, ktrlen, size;
82         pid_t do_pid = -1;
83         void *m;
84         int trpoints = ALL_POINTS;
85         char *cp;
86
87         setlocale(LC_CTYPE, "");
88
89         while ((ch = getopt(argc,argv,"acf:djlm:np:RTt:")) != -1)
90                 switch((char)ch) {
91                 case 'f':
92                         tracefile = optarg;
93                         break;
94                 case 'j':
95                         fixedformat = 1;
96                         break;
97                 case 'c':
98                         cpustamp = 1;
99                         break;
100                 case 'a':
101                         timestamp = 2;  /* relative timestamp */
102                         cpustamp = 1;
103                         break;
104                 case 'd':
105                         decimal = 1;
106                         break;
107                 case 'l':
108                         tail = 1;
109                         break;
110                 case 'm':
111                         maxdata = atoi(optarg);
112                         break;
113                 case 'n':
114                         fancy = 0;
115                         break;
116                 case 'p':
117                         do_pid = strtoul(optarg, &cp, 0);
118                         if (*cp != 0)
119                                 errx(1,"invalid number %s", optarg);
120                         break;
121                 case 'R':
122                         timestamp = 2;  /* relative timestamp */
123                         break;
124                 case 'T':
125                         timestamp = 1;
126                         break;
127                 case 't':
128                         trpoints = getpoints(optarg);
129                         if (trpoints < 0)
130                                 errx(1, "unknown trace point in %s", optarg);
131                         break;
132                 default:
133                         usage();
134                 }
135
136         if (argc > optind)
137                 usage();
138
139         m = (void *)malloc(size = 1025);
140         if (m == NULL)
141                 errx(1, "%s", strerror(ENOMEM));
142         if (!freopen(tracefile, "r", stdin))
143                 err(1, "%s", tracefile);
144         while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) {
145                 if (trpoints & (1 << ktr_header.ktr_type) &&
146                     (do_pid == -1 || ktr_header.ktr_pid == do_pid))
147                         col = dumpheader(&ktr_header);
148                 else
149                         col = -1;
150                 if ((ktrlen = ktr_header.ktr_len) < 0)
151                         errx(1, "bogus length 0x%x", ktrlen);
152                 if (ktrlen > size) {
153                         m = (void *)realloc(m, ktrlen+1);
154                         if (m == NULL)
155                                 errx(1, "%s", strerror(ENOMEM));
156                         size = ktrlen;
157                 }
158                 if (ktrlen && fread_tail(m, ktrlen, 1) == 0)
159                         errx(1, "data too short");
160                 if ((trpoints & (1<<ktr_header.ktr_type)) == 0)
161                         continue;
162                 if (col == -1)
163                         continue;
164                 switch (ktr_header.ktr_type) {
165                 case KTR_SYSCALL:
166                         ktrsyscall((struct ktr_syscall *)m);
167                         break;
168                 case KTR_SYSRET:
169                         ktrsysret((struct ktr_sysret *)m);
170                         break;
171                 case KTR_NAMEI:
172                 case KTR_SYSCTL:
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                         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                 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         case KTR_SYSCTL:
237                 type = "SCTL";
238                 break;
239         default:
240                 sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type);
241                 type = unknown;
242         }
243
244         if (kth->ktr_tid || (kth->ktr_flags & KTRH_THREADED) || fixedformat)
245                 col = printf("%5d:%-4d", kth->ktr_pid, kth->ktr_tid);
246         else
247                 col = printf("%5d", kth->ktr_pid);
248         if (cpustamp)
249                 col += printf(" %2d", KTRH_CPUID_DECODE(kth->ktr_flags));
250         col += printf(" %-8.*s ", MAXCOMLEN, kth->ktr_comm);
251         if (timestamp) {
252                 if (timestamp == 2) {
253                         temp = kth->ktr_time;
254                         timevalsub(&kth->ktr_time, &prevtime);
255                         prevtime = temp;
256                 }
257                 col += printf("%ld.%06ld ",
258                     kth->ktr_time.tv_sec, kth->ktr_time.tv_usec);
259         }
260         col += printf("%s  ", type);
261         return col;
262 }
263
264 #include <sys/syscall.h>
265 #define KTRACE
266 #include <kern/syscalls.c>
267 #undef KTRACE
268 int nsyscalls = sizeof (syscallnames) / sizeof (syscallnames[0]);
269
270 static const char *ptrace_ops[] = {
271         "PT_TRACE_ME",  "PT_READ_I",    "PT_READ_D",    "PT_READ_U",
272         "PT_WRITE_I",   "PT_WRITE_D",   "PT_WRITE_U",   "PT_CONTINUE",
273         "PT_KILL",      "PT_STEP",      "PT_ATTACH",    "PT_DETACH",
274 };
275
276 static void
277 ktrsyscall(struct ktr_syscall *ktr)
278 {
279         int narg = ktr->ktr_narg;
280         register_t *ip;
281
282         if (ktr->ktr_code >= nsyscalls || ktr->ktr_code < 0)
283                 printf("[%d]", ktr->ktr_code);
284         else
285                 printf("%s", syscallnames[ktr->ktr_code]);
286         ip = &ktr->ktr_args[0];
287         if (narg) {
288                 char c = '(';
289                 if (fancy) {
290
291 #define print_number(i,n,c) do {                      \
292         if (decimal)                                  \
293                 printf("%c%ld", c, (long)*i);   \
294         else                                          \
295                 printf("%c%#lx", c, (long)*i);  \
296         i++;                                          \
297         n--;                                          \
298         c = ',';                                      \
299         } while (0);
300
301                         if (ktr->ktr_code == SYS_ioctl) {
302                                 const char *cp;
303                                 print_number(ip,narg,c);
304                                 if ((cp = ioctlname(*ip)) != NULL)
305                                         printf(",%s", cp);
306                                 else {
307                                         if (decimal)
308                                                 printf(",%ld", (long)*ip);
309                                         else
310                                                 printf(",%#lx ", (long)*ip);
311                                 }
312                                 c = ',';
313                                 ip++;
314                                 narg--;
315                         } else if (ktr->ktr_code == SYS_access ||
316                                    ktr->ktr_code == SYS_eaccess ||
317                                    ktr->ktr_code == SYS_faccessat) {
318                                 if (ktr->ktr_code == SYS_faccessat)
319                                         print_number(ip,narg,c);
320                                 print_number(ip,narg,c);
321                                 putchar(',');
322                                 accessmodename ((int)*ip);
323                                 ip++;
324                                 narg--;
325                                 if (ktr->ktr_code == SYS_faccessat) {
326                                         putchar(',');
327                                         atflagsname((int)*ip);
328                                         ip++;
329                                         narg--;
330                                 }
331                         } else if (ktr->ktr_code == SYS_open ||
332                                    ktr->ktr_code == SYS_mq_open) {
333                                 int     flags;
334                                 int     mode;
335                                 print_number(ip,narg,c);
336                                 flags = *ip;
337                                 mode = *++ip;
338                                 putchar(',');
339                                 flagsandmodename (flags, mode, decimal);
340                                 ip++;
341                                 narg-=2;
342                         } else if (ktr->ktr_code == SYS_wait4) {
343                                 print_number(ip,narg,c);
344                                 print_number(ip,narg,c);
345                                 putchar(',');
346                                 wait4optname ((int)*ip);
347                                 ip++;
348                                 narg--;
349                         } else if (ktr->ktr_code == SYS_chmod ||
350                                    ktr->ktr_code == SYS_fchmod ||
351                                    ktr->ktr_code == SYS_fchmodat ||
352                                    ktr->ktr_code == SYS_lchmod) {
353                                 if (ktr->ktr_code == SYS_fchmodat)
354                                         print_number(ip,narg,c);
355                                 print_number(ip,narg,c);
356                                 putchar(',');
357                                 modename ((int)*ip);
358                                 ip++;
359                                 narg--;
360                                 if (ktr->ktr_code == SYS_fchmodat) {
361                                         putchar(',');
362                                         atflagsname((int)*ip);
363                                         ip++;
364                                         narg--;
365                                 }
366                         } else if (ktr->ktr_code == SYS_fchownat ||
367                                    ktr->ktr_code == SYS_fstatat ||
368                                    ktr->ktr_code == SYS_linkat ||
369                                    ktr->ktr_code == SYS_unlinkat ||
370                                    ktr->ktr_code == SYS_utimensat) {
371                                 print_number(ip,narg,c);
372                                 print_number(ip,narg,c);
373                                 if (ktr->ktr_code != SYS_unlinkat)
374                                         print_number(ip,narg,c);
375                                 if (ktr->ktr_code == SYS_fchownat ||
376                                     ktr->ktr_code == SYS_linkat)
377                                         print_number(ip,narg,c);
378                                 putchar(',');
379                                 atflagsname((int)*ip);
380                                 ip++;
381                                 narg--;
382                         } else if (ktr->ktr_code == SYS_mknod) {
383                                 print_number(ip,narg,c);
384                                 putchar(',');
385                                 modename ((int)*ip);
386                                 ip++;
387                                 narg--;
388                         } else if (ktr->ktr_code == SYS_getfsstat ||
389                                    ktr->ktr_code == SYS_getvfsstat) {
390                                 print_number(ip,narg,c);
391                                 if (ktr->ktr_code == SYS_getvfsstat)
392                                         print_number(ip,narg,c);
393                                 print_number(ip,narg,c);
394                                 putchar(',');
395                                 getfsstatflagsname ((int)*ip);
396                                 ip++;
397                                 narg--;
398                         } else if (ktr->ktr_code == SYS_mount) {
399                                 print_number(ip,narg,c);
400                                 print_number(ip,narg,c);
401                                 putchar(',');
402                                 mountflagsname ((int)*ip);
403                                 ip++;
404                                 narg--;
405                         } else if (ktr->ktr_code == SYS_unmount) {
406                                 print_number(ip,narg,c);
407                                 putchar(',');
408                                 mountflagsname ((int)*ip);
409                                 ip++;
410                                 narg--;
411                         } else if (ktr->ktr_code == SYS_recvmsg ||
412                                    ktr->ktr_code == SYS_sendmsg) {
413                                 print_number(ip,narg,c);
414                                 print_number(ip,narg,c);
415                                 putchar(',');
416                                 sendrecvflagsname ((int)*ip);
417                                 ip++;
418                                 narg--;
419                         } else if (ktr->ktr_code == SYS_recvfrom ||
420                                    ktr->ktr_code == SYS_sendto) {
421                                 print_number(ip,narg,c);
422                                 print_number(ip,narg,c);
423                                 print_number(ip,narg,c);
424                                 putchar(',');
425                                 sendrecvflagsname ((int)*ip);
426                                 ip++;
427                                 narg--;
428                         } else if (ktr->ktr_code == SYS_chflags ||
429                                    ktr->ktr_code == SYS_chflagsat ||
430                                    ktr->ktr_code == SYS_fchflags ||
431                                    ktr->ktr_code == SYS_lchflags) {
432                                 if (ktr->ktr_code == SYS_chflagsat)
433                                         print_number(ip,narg,c);
434                                 print_number(ip,narg,c);
435                                 putchar(',');
436                                 chflagsname((long)*ip);
437                                 ip++;
438                                 narg--;
439                                 if (ktr->ktr_code == SYS_chflagsat) {
440                                         putchar(',');
441                                         atflagsname((int)*ip);
442                                         ip++;
443                                         narg--;
444                                 }
445                         } else if (ktr->ktr_code == SYS_kill) {
446                                 print_number(ip,narg,c);
447                                 putchar(',');
448                                 signame((int)*ip);
449                                 ip++;
450                                 narg--;
451                         } else if (ktr->ktr_code == SYS_reboot) {
452                                 putchar('(');
453                                 rebootoptname((int)*ip);
454                                 ip++;
455                                 narg--;
456                         } else if (ktr->ktr_code == SYS_umask) {
457                                 putchar('(');
458                                 modename((int)*ip);
459                                 ip++;
460                                 narg--;
461                         } else if (ktr->ktr_code == SYS_msync) {
462                                 print_number(ip,narg,c);
463                                 print_number(ip,narg,c);
464                                 putchar(',');
465                                 msyncflagsname((int)*ip);
466                                 ip++;
467                                 narg--;
468                         } else if (ktr->ktr_code == SYS_mmap) {
469                                 print_number(ip,narg,c);
470                                 print_number(ip,narg,c);
471                                 putchar(',');
472                                 mmapprotname ((int)*ip);
473                                 putchar(',');
474                                 ip++;
475                                 narg--;
476                                 mmapflagsname ((int)*ip);
477                                 ip++;
478                                 narg--;
479                         } else if (ktr->ktr_code == SYS_mprotect) {
480                                 print_number(ip,narg,c);
481                                 print_number(ip,narg,c);
482                                 putchar(',');
483                                 mmapprotname ((int)*ip);
484                                 ip++;
485                                 narg--;
486                         } else if (ktr->ktr_code == SYS_madvise) {
487                                 print_number(ip,narg,c);
488                                 print_number(ip,narg,c);
489                                 putchar(',');
490                                 madvisebehavname((int)*ip);
491                                 ip++;
492                                 narg--;
493                         } else if (ktr->ktr_code == SYS_setpriority) {
494                                 putchar('(');
495                                 prioname((int)*ip);
496                                 ip++;
497                                 narg--;
498                                 c = ',';
499                                 print_number(ip,narg,c);
500                                 print_number(ip,narg,c);
501                         } else if (ktr->ktr_code == SYS_fcntl) {
502                                 int cmd;
503                                 int arg;
504                                 print_number(ip,narg,c);
505                                 cmd = *ip;
506                                 arg = *++ip;
507                                 putchar(',');
508                                 fcntlcmdname(cmd, arg, decimal);
509                                 ip++;
510                                 narg-=2;
511                         } else if (ktr->ktr_code == SYS_socket) {
512                                 putchar('(');
513                                 sockdomainname((int)*ip);
514                                 ip++;
515                                 narg--;
516                                 putchar(',');
517                                 socktypename((int)*ip);
518                                 ip++;
519                                 narg--;
520                                 c = ',';
521                         } else if (ktr->ktr_code == SYS_setsockopt ||
522                                    ktr->ktr_code == SYS_getsockopt) {
523                                 print_number(ip,narg,c);
524                                 putchar(',');
525                                 sockoptlevelname((int)*ip, decimal);
526                                 ip++;
527                                 narg--;
528                                 putchar(',');
529                                 sockoptname((int)*ip);
530                                 ip++;
531                                 narg--;
532                         } else if (ktr->ktr_code == SYS_lseek) {
533                                 print_number(ip,narg,c);
534                                 /* Hidden 'pad' argument, not in lseek(2) */
535                                 print_number(ip,narg,c);
536                                 print_number(ip,narg,c);
537                                 putchar(',');
538                                 whencename ((int)*ip);
539                                 ip++;
540                                 narg--;
541                         } else if (ktr->ktr_code == SYS_flock) {
542                                 print_number(ip,narg,c);
543                                 putchar(',');
544                                 flockname((int)*ip);
545                                 ip++;
546                                 narg--;
547                         } else if (ktr->ktr_code == SYS_mkfifo ||
548                                    ktr->ktr_code == SYS_mkdir) {
549                                 print_number(ip,narg,c);
550                                 putchar(',');
551                                 modename((int)*ip);
552                                 ip++;
553                                 narg--;
554                         } else if (ktr->ktr_code == SYS_shutdown) {
555                                 print_number(ip,narg,c);
556                                 putchar(',');
557                                 shutdownhowname((int)*ip);
558                                 ip++;
559                                 narg--;
560                         } else if (ktr->ktr_code == SYS_socketpair) {
561                                 putchar('(');
562                                 sockdomainname((int)*ip);
563                                 ip++;
564                                 narg--;
565                                 putchar(',');
566                                 socktypename((int)*ip);
567                                 ip++;
568                                 narg--;
569                                 c = ',';
570                         } else if (ktr->ktr_code == SYS_getrlimit ||
571                                    ktr->ktr_code == SYS_setrlimit) {
572                                 putchar('(');
573                                 rlimitname((int)*ip);
574                                 ip++;
575                                 narg--;
576                                 c = ',';
577                         } else if (ktr->ktr_code == SYS_quotactl) {
578                                 print_number(ip,narg,c);
579                                 quotactlname((int)*ip);
580                                 ip++;
581                                 narg--;
582                                 c = ',';
583                         } else if (ktr->ktr_code == SYS_rtprio) {
584                                 putchar('(');
585                                 rtprioname((int)*ip);
586                                 ip++;
587                                 narg--;
588                                 c = ',';
589                         } else if (ktr->ktr_code == SYS___semctl) {
590                                 print_number(ip,narg,c);
591                                 print_number(ip,narg,c);
592                                 semctlname((int)*ip);
593                                 ip++;
594                                 narg--;
595                         } else if (ktr->ktr_code == SYS_semget) {
596                                 print_number(ip,narg,c);
597                                 print_number(ip,narg,c);
598                                 semgetname((int)*ip);
599                                 ip++;
600                                 narg--;
601                         } else if (ktr->ktr_code == SYS_msgctl) {
602                                 print_number(ip,narg,c);
603                                 shmctlname((int)*ip);
604                                 ip++;
605                                 narg--;
606                         } else if (ktr->ktr_code == SYS_shmat) {
607                                 print_number(ip,narg,c);
608                                 print_number(ip,narg,c);
609                                 shmatname((int)*ip);
610                                 ip++;
611                                 narg--;
612                         } else if (ktr->ktr_code == SYS_shmctl) {
613                                 print_number(ip,narg,c);
614                                 shmctlname((int)*ip);
615                                 ip++;
616                                 narg--;
617                         } else if (ktr->ktr_code == SYS_minherit) {
618                                 print_number(ip,narg,c);
619                                 print_number(ip,narg,c);
620                                 minheritname((int)*ip);
621                                 ip++;
622                                 narg--;
623                         } else if (ktr->ktr_code == SYS_rfork) {
624                                 putchar('(');
625                                 rforkname((int)*ip);
626                                 ip++;
627                                 narg--;
628                                 c = ',';
629                         } else if (ktr->ktr_code == SYS_lio_listio) {
630                                 putchar('(');
631                                 lio_listioname((int)*ip);
632                                 ip++;
633                                 narg--;
634                                 c = ',';
635                         } else if (ktr->ktr_code == SYS_mlockall) {
636                                 putchar('(');
637                                 mlockallname((int)*ip);
638                                 ip++;
639                                 narg--;
640                         } else if (ktr->ktr_code == SYS_sched_setscheduler) {
641                                 print_number(ip,narg,c);
642                                 schedpolicyname((int)*ip);
643                                 ip++;
644                                 narg--;
645                         } else if (ktr->ktr_code == SYS_sched_get_priority_max ||
646                                    ktr->ktr_code == SYS_sched_get_priority_min) {
647                                 putchar('(');
648                                 schedpolicyname((int)*ip);
649                                 ip++;
650                                 narg--;
651                         } else if (ktr->ktr_code == SYS_sendfile) {
652                                 print_number(ip,narg,c);
653                                 print_number(ip,narg,c);
654                                 print_number(ip,narg,c);
655                                 print_number(ip,narg,c);
656                                 print_number(ip,narg,c);
657                                 print_number(ip,narg,c);
658                                 sendfileflagsname((int)*ip);
659                                 ip++;
660                                 narg--;
661                         } else if (ktr->ktr_code == SYS_kldsym) {
662                                 print_number(ip,narg,c);
663                                 kldsymcmdname((int)*ip);
664                                 ip++;
665                                 narg--;
666                         } else if (ktr->ktr_code == SYS_sigprocmask) {
667                                 putchar('(');
668                                 sigprocmaskhowname((int)*ip);
669                                 ip++;
670                                 narg--;
671                                 c = ',';
672                         } else if (ktr->ktr_code == SYS___acl_get_file ||
673                                    ktr->ktr_code == SYS___acl_set_file ||
674                                    ktr->ktr_code == SYS___acl_get_fd ||
675                                    ktr->ktr_code == SYS___acl_set_fd ||
676                                    ktr->ktr_code == SYS___acl_delete_file ||
677                                    ktr->ktr_code == SYS___acl_delete_fd ||
678                                    ktr->ktr_code == SYS___acl_aclcheck_file ||
679                                    ktr->ktr_code == SYS___acl_aclcheck_fd) {
680                                 print_number(ip,narg,c);
681                                 acltypename((int)*ip);
682                                 ip++;
683                                 narg--;
684                         } else if (ktr->ktr_code == SYS_sigaction) {
685                                 putchar('(');
686                                 signame((int)*ip);
687                                 ip++;
688                                 narg--;
689                                 c = ',';
690                         } else if (ktr->ktr_code == SYS_extattrctl) {
691                                 print_number(ip,narg,c);
692                                 extattrctlname((int)*ip);
693                                 ip++;
694                                 narg--;
695                         } else if (ktr->ktr_code == SYS_ptrace) {
696                                 if (*ip < (register_t)NELEM(ptrace_ops) && *ip >= 0)
697                                         printf("(%s", ptrace_ops[*ip]);
698 #ifdef PT_GETREGS
699                                 else if (*ip == PT_GETREGS)
700                                         printf("(%s", "PT_GETREGS");
701 #endif
702 #ifdef PT_SETREGS
703                                 else if (*ip == PT_SETREGS)
704                                         printf("(%s", "PT_SETREGS");
705 #endif
706 #ifdef PT_GETFPREGS
707                                 else if (*ip == PT_GETFPREGS)
708                                         printf("(%s", "PT_GETFPREGS");
709 #endif
710 #ifdef PT_SETFPREGS
711                                 else if (*ip == PT_SETFPREGS)
712                                         printf("(%s", "PT_SETFPREGS");
713 #endif
714 #ifdef PT_GETDBREGS
715                                 else if (*ip == PT_GETDBREGS)
716                                         printf("(%s", "PT_GETDBREGS");
717 #endif
718 #ifdef PT_SETDBREGS
719                                 else if (*ip == PT_SETDBREGS)
720                                         printf("(%s", "PT_SETDBREGS");
721 #endif
722                                 else
723                                         printf("(%ld", (long)*ip);
724                                 c = ',';
725                                 ip++;
726                                 narg--;
727                         } else if (ktr->ktr_code == SYS_clock_getres ||
728                                    ktr->ktr_code == SYS_clock_gettime ||
729                                    ktr->ktr_code == SYS_clock_settime) {
730                                 putchar('(');
731                                 clockidname((int)*ip);
732                                 ip++;
733                                 narg--;
734                                 c = ',';
735                         } else if (ktr->ktr_code == SYS_fpathconf ||
736                                    ktr->ktr_code == SYS_lpathconf ||
737                                    ktr->ktr_code == SYS_pathconf) {
738                                 print_number(ip,narg,c);
739                                 putchar(',');
740                                 pathconfname((int)*ip);
741                                 ip++;
742                                 narg--;
743                         } else if (ktr->ktr_code == SYS_kenv) {
744                                 putchar('(');
745                                 kenvactname((int)*ip);
746                                 ip++;
747                                 narg--;
748                                 c = ',';
749                         } else if (ktr->ktr_code == SYS_usched_set) {
750                                 print_number(ip,narg,c);
751                                 putchar(',');
752                                 uschedcmdname((int)*ip);
753                                 ip++;
754                                 narg--;
755                         } else if (ktr->ktr_code == SYS_sys_checkpoint) {
756                                 putchar('(');
757                                 ckpttypename((int)*ip);
758                                 ip++;
759                                 narg--;
760                                 c = ',';
761                         } else if (ktr->ktr_code == SYS_procctl) {
762                                 print_number(ip,narg,c);
763                                 print_number(ip,narg,c);
764                                 putchar(',');
765                                 procctlcmdname((int)*ip);
766                                 ip++;
767                                 narg--;
768                                 c = ',';
769                         } else if (ktr->ktr_code == SYS_mountctl) {
770                                 print_number(ip,narg,c);
771                                 putchar(',');
772                                 mountctlopname((int)*ip);
773                                 ip++;
774                                 narg--;
775                                 c = ',';
776                         } else if (ktr->ktr_code == SYS_varsym_list ||
777                                    ktr->ktr_code == SYS_varsym_set) {
778                                 putchar('(');
779                                 varsymlvlname((int)*ip);
780                                 ip++;
781                                 narg--;
782                                 c = ',';
783                         }
784                 }
785                 while (narg > 0) {
786                         print_number(ip,narg,c);
787                 }
788                 putchar(')');
789         }
790         putchar('\n');
791 }
792
793 static void
794 ktrsysret(struct ktr_sysret *ktr)
795 {
796         register_t ret = ktr->ktr_retval;
797         int error = ktr->ktr_error;
798         int code = ktr->ktr_code;
799
800         if (code >= nsyscalls || code < 0)
801                 printf("[%d] ", code);
802         else
803                 printf("%s ", syscallnames[code]);
804
805         if (error == 0) {
806                 if (fancy) {
807                         printf("%ld", (long)ret);
808                         if (ret < 0 || ret > 9)
809                                 printf("/%#lx", (long)ret);
810                 } else {
811                         if (decimal)
812                                 printf("%ld", (long)ret);
813                         else
814                                 printf("%#lx", (long)ret);
815                 }
816         } else if (error == ERESTART)
817                 printf("RESTART");
818         else if (error == EJUSTRETURN)
819                 printf("JUSTRETURN");
820         else {
821                 printf("-1 errno %d", ktr->ktr_error);
822                 if (fancy)
823                         printf(" %s", strerror(ktr->ktr_error));
824         }
825         putchar('\n');
826 }
827
828 static void
829 ktrnamei(char *cp, int len)
830 {
831         printf("\"%.*s\"\n", len, cp);
832 }
833
834 static void
835 ktrgenio(struct ktr_genio *ktr, int len)
836 {
837         int datalen = len - sizeof (struct ktr_genio);
838         char *dp = (char *)ktr + sizeof (struct ktr_genio);
839         char *cp;
840         int col = 0;
841         int width;
842         char visbuf[5];
843         static int screenwidth = 0;
844
845         if (screenwidth == 0) {
846                 struct winsize ws;
847
848                 if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 &&
849                     ws.ws_col > 8)
850                         screenwidth = ws.ws_col;
851                 else
852                         screenwidth = 80;
853         }
854         printf("fd %d %s %d byte%s\n", ktr->ktr_fd,
855                 ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen,
856                 datalen == 1 ? "" : "s");
857         if (maxdata && datalen > maxdata)
858                 datalen = maxdata;
859         printf("       \"");
860         col = 8;
861         for (;datalen > 0; datalen--, dp++) {
862                 vis(visbuf, *dp, VIS_CSTYLE, *(dp+1));
863                 cp = visbuf;
864                 /*
865                  * Keep track of printables and
866                  * space chars (like fold(1)).
867                  */
868                 if (col == 0) {
869                         putchar('\t');
870                         col = 8;
871                 }
872                 switch(*cp) {
873                 case '\n':
874                         col = 0;
875                         putchar('\n');
876                         continue;
877                 case '\t':
878                         width = 8 - (col&07);
879                         break;
880                 default:
881                         width = strlen(cp);
882                 }
883                 if (col + width > (screenwidth-2)) {
884                         printf("\\\n\t");
885                         col = 8;
886                 }
887                 col += width;
888                 do {
889                         putchar(*cp++);
890                 } while (*cp);
891         }
892         if (col == 0)
893                 printf("       ");
894         printf("\"\n");
895 }
896
897 const char *signames[NSIG] = {
898         "NULL", "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT",     /*  1 - 6  */
899         "EMT", "FPE", "KILL", "BUS", "SEGV", "SYS",             /*  7 - 12 */
900         "PIPE", "ALRM",  "TERM", "URG", "STOP", "TSTP",         /* 13 - 18 */
901         "CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU",           /* 19 - 24 */
902         "XFSZ", "VTALRM", "PROF", "WINCH", "29", "USR1",        /* 25 - 30 */
903         "USR2", NULL,                                           /* 31 - 32 */
904 };
905
906 static void
907 ktrpsig(struct ktr_psig *psig)
908 {
909         printf("SIG%s ", signames[psig->signo]);
910         if (psig->action == SIG_DFL)
911                 printf("SIG_DFL\n");
912         else
913                 printf("caught handler=0x%lx mask=0x%x code=0x%x\n",
914                     (u_long)psig->action, psig->mask.__bits[0], psig->code);
915 }
916
917 static void
918 ktrcsw(struct ktr_csw *cs)
919 {
920         printf("%s %s\n", cs->out ? "stop" : "resume",
921                 cs->user ? "user" : "kernel");
922 }
923
924 #define UTRACE_DLOPEN_START             1
925 #define UTRACE_DLOPEN_STOP              2
926 #define UTRACE_DLCLOSE_START            3
927 #define UTRACE_DLCLOSE_STOP             4
928 #define UTRACE_LOAD_OBJECT              5
929 #define UTRACE_UNLOAD_OBJECT            6
930 #define UTRACE_ADD_RUNDEP               7
931 #define UTRACE_PRELOAD_FINISHED         8
932 #define UTRACE_INIT_CALL                9
933 #define UTRACE_FINI_CALL                10
934
935 struct utrace_rtld {
936         char sig[4];                            /* 'RTLD' */
937         int event;
938         void *handle;
939         void *mapbase;
940         size_t mapsize;
941         int refcnt;
942         char name[MAXPATHLEN];
943 };
944
945 static void
946 ktruser_rtld(int len, unsigned char *p)
947 {
948         struct utrace_rtld *ut = (struct utrace_rtld *)p;
949         void *parent;
950         int mode;
951
952         switch (ut->event) {
953         case UTRACE_DLOPEN_START:
954                 mode = ut->refcnt;
955                 printf("dlopen(%s, ", ut->name);
956                 switch (mode & RTLD_MODEMASK) {
957                 case RTLD_NOW:
958                         printf("RTLD_NOW");
959                         break;
960                 case RTLD_LAZY:
961                         printf("RTLD_LAZY");
962                         break;
963                 default:
964                         printf("%#x", mode & RTLD_MODEMASK);
965                 }
966                 if (mode & RTLD_GLOBAL)
967                         printf(" | RTLD_GLOBAL");
968                 if (mode & RTLD_TRACE)
969                         printf(" | RTLD_TRACE");
970                 if (mode & ~(RTLD_MODEMASK | RTLD_GLOBAL | RTLD_TRACE))
971                         printf(" | %#x", mode &
972                             ~(RTLD_MODEMASK | RTLD_GLOBAL | RTLD_TRACE));
973                 printf(")\n");
974                 break;
975         case UTRACE_DLOPEN_STOP:
976                 printf("%p = dlopen(%s) ref %d\n", ut->handle, ut->name,
977                     ut->refcnt);
978                 break;
979         case UTRACE_DLCLOSE_START:
980                 printf("dlclose(%p) (%s, %d)\n", ut->handle, ut->name,
981                     ut->refcnt);
982                 break;
983         case UTRACE_DLCLOSE_STOP:
984                 printf("dlclose(%p) finished\n", ut->handle);
985                 break;
986         case UTRACE_LOAD_OBJECT:
987                 printf("RTLD: loaded   %p @ %p - %p (%s)\n", ut->handle,
988                     ut->mapbase, (char *)ut->mapbase + ut->mapsize - 1,
989                     ut->name);
990                 break;
991         case UTRACE_UNLOAD_OBJECT:
992                 printf("RTLD: unloaded %p @ %p - %p (%s)\n", ut->handle,
993                     ut->mapbase, (char *)ut->mapbase + ut->mapsize - 1,
994                     ut->name);
995                 break;
996         case UTRACE_ADD_RUNDEP:
997                 parent = ut->mapbase;
998                 printf("RTLD: %p now depends on %p (%s, %d)\n", parent,
999                     ut->handle, ut->name, ut->refcnt);
1000                 break;
1001         case UTRACE_PRELOAD_FINISHED:
1002                 printf("RTLD: LD_PRELOAD finished\n");
1003                 break;
1004         case UTRACE_INIT_CALL:
1005                 printf("RTLD: init %p for %p (%s)\n", ut->mapbase, ut->handle,
1006                     ut->name);
1007                 break;
1008         case UTRACE_FINI_CALL:
1009                 printf("RTLD: fini %p for %p (%s)\n", ut->mapbase, ut->handle,
1010                     ut->name);
1011                 break;
1012         default:
1013                 p += 4;
1014                 len -= 4;
1015                 printf("RTLD: %d ", len);
1016                 while (len--)
1017                         if (decimal)
1018                                 printf(" %d", *p++);
1019                         else
1020                                 printf(" %02x", *p++);
1021                 printf("\n");
1022         }
1023 }
1024
1025 struct utrace_malloc {
1026         void *p;
1027         size_t s;
1028         void *r;
1029 };
1030
1031 static void
1032 ktruser_malloc(int len __unused, unsigned char *p)
1033 {
1034         struct utrace_malloc *ut = (struct utrace_malloc *)p;
1035
1036         if (ut->p == NULL) {
1037                 if (ut->s == 0 && ut->r == NULL)
1038                         printf("malloc_init()\n");
1039                 else
1040                         printf("%p = malloc(%zu)\n", ut->r, ut->s);
1041         } else {
1042                 if (ut->s == 0)
1043                         printf("free(%p)\n", ut->p);
1044                 else
1045                         printf("%p = realloc(%p, %zu)\n", ut->r, ut->p, ut->s);
1046         }
1047 }
1048
1049 static void
1050 ktruser(int len, unsigned char *p)
1051 {
1052
1053         if (len >= 8 && bcmp(p, "RTLD", 4) == 0) {
1054                 ktruser_rtld(len, p);
1055                 return;
1056         }
1057
1058         if (len == sizeof(struct utrace_malloc)) {
1059                 ktruser_malloc(len, p);
1060                 return;
1061         }
1062
1063         printf("%d ", len);
1064         while (len--)
1065                 printf(" %02x", *p++);
1066         printf("\n");
1067 }
1068
1069 static void
1070 usage(void)
1071 {
1072         fprintf(stderr,
1073             "usage: kdump [-dnlRT] [-f trfile] [-m maxdata] [-t [cnisuw]] [-p pid]\n");
1074         exit(1);
1075 }
1076
1077 static void
1078 timevalsub(struct timeval *t1, struct timeval *t2)
1079 {
1080         t1->tv_sec -= t2->tv_sec;
1081         t1->tv_usec -= t2->tv_usec;
1082         timevalfix(t1);
1083 }
1084
1085 static void
1086 timevalfix(struct timeval *t1)
1087 {
1088         if (t1->tv_usec < 0) {
1089                 t1->tv_sec--;
1090                 t1->tv_usec += 1000000;
1091         }
1092         if (t1->tv_usec >= 1000000) {
1093                 t1->tv_sec++;
1094                 t1->tv_usec -= 1000000;
1095         }
1096 }