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