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