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