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