Add code to parse the utrace(2) entries generated by malloc(3) in a more
[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.12 2008/10/15 16:04:11 hasso 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         register 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(register struct ktr_syscall *ktr)
248 {
249         register narg = ktr->ktr_narg;
250         register 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                                 print_number(ip,narg,c);
417                                 print_number(ip,narg,c);
418                                 (void)putchar(',');
419                                 prioname((int)*ip);
420                                 ip++;
421                                 narg--;
422                         } else if (ktr->ktr_code == SYS_fcntl) {
423                                 int cmd;
424                                 int arg;
425                                 print_number(ip,narg,c);
426                                 cmd = *ip;
427                                 arg = *++ip;
428                                 (void)putchar(',');
429                                 fcntlcmdname(cmd, arg, decimal);
430                                 ip++;
431                                 narg-=2;
432                         } else if (ktr->ktr_code == SYS_socket) {
433                                 (void)putchar('(');
434                                 sockdomainname((int)*ip);
435                                 ip++;
436                                 narg--;
437                                 (void)putchar(',');
438                                 socktypename((int)*ip);
439                                 ip++;
440                                 narg--;
441                                 c = ',';
442                         } else if (ktr->ktr_code == SYS_setsockopt ||
443                                    ktr->ktr_code == SYS_getsockopt) {
444                                 print_number(ip,narg,c);
445                                 (void)putchar(',');
446                                 sockoptlevelname((int)*ip, decimal);
447                                 ip++;
448                                 narg--;
449                                 (void)putchar(',');
450                                 sockoptname((int)*ip);
451                                 ip++;
452                                 narg--;
453                         } else if (ktr->ktr_code == SYS_lseek) {
454                                 print_number(ip,narg,c);
455                                 /* Hidden 'pad' argument, not in lseek(2) */
456                                 print_number(ip,narg,c);
457                                 print_number(ip,narg,c);
458                                 (void)putchar(',');
459                                 whencename ((int)*ip);
460                                 ip++;
461                                 narg--;
462                         } else if (ktr->ktr_code == SYS_flock) {
463                                 print_number(ip,narg,c);
464                                 (void)putchar(',');
465                                 flockname((int)*ip);
466                                 ip++;
467                                 narg--;
468                         } else if (ktr->ktr_code == SYS_mkfifo ||
469                                    ktr->ktr_code == SYS_mkdir) {
470                                 print_number(ip,narg,c);
471                                 (void)putchar(',');
472                                 modename((int)*ip);
473                                 ip++;
474                                 narg--;
475                         } else if (ktr->ktr_code == SYS_shutdown) {
476                                 print_number(ip,narg,c);
477                                 (void)putchar(',');
478                                 shutdownhowname((int)*ip);
479                                 ip++;
480                                 narg--;
481                         } else if (ktr->ktr_code == SYS_socketpair) {
482                                 (void)putchar('(');
483                                 sockdomainname((int)*ip);
484                                 ip++;
485                                 narg--;
486                                 (void)putchar(',');
487                                 socktypename((int)*ip);
488                                 ip++;
489                                 narg--;
490                                 c = ',';
491                         } else if (ktr->ktr_code == SYS_getrlimit ||
492                                    ktr->ktr_code == SYS_setrlimit) {
493                                 (void)putchar('(');
494                                 rlimitname((int)*ip);
495                                 ip++;
496                                 narg--;
497                                 c = ',';
498                         } else if (ktr->ktr_code == SYS_quotactl) {
499                                 print_number(ip,narg,c);
500                                 quotactlname((int)*ip);
501                                 ip++;
502                                 narg--;
503                                 c = ',';
504                         } else if (ktr->ktr_code == SYS_rtprio) {
505                                 (void)putchar('(');
506                                 rtprioname((int)*ip);
507                                 ip++;
508                                 narg--;
509                                 c = ',';
510                         } else if (ktr->ktr_code == SYS___semctl) {
511                                 print_number(ip,narg,c);
512                                 print_number(ip,narg,c);
513                                 semctlname((int)*ip);
514                                 ip++;
515                                 narg--;
516                         } else if (ktr->ktr_code == SYS_semget) {
517                                 print_number(ip,narg,c);
518                                 print_number(ip,narg,c);
519                                 semgetname((int)*ip);
520                                 ip++;
521                                 narg--;
522                         } else if (ktr->ktr_code == SYS_msgctl) {
523                                 print_number(ip,narg,c);
524                                 shmctlname((int)*ip);
525                                 ip++;
526                                 narg--;
527                         } else if (ktr->ktr_code == SYS_shmat) {
528                                 print_number(ip,narg,c);
529                                 print_number(ip,narg,c);
530                                 shmatname((int)*ip);
531                                 ip++;
532                                 narg--;
533                         } else if (ktr->ktr_code == SYS_shmctl) {
534                                 print_number(ip,narg,c);
535                                 shmctlname((int)*ip);
536                                 ip++;
537                                 narg--;
538                         } else if (ktr->ktr_code == SYS_minherit) {
539                                 print_number(ip,narg,c);
540                                 print_number(ip,narg,c);
541                                 minheritname((int)*ip);
542                                 ip++;
543                                 narg--;
544                         } else if (ktr->ktr_code == SYS_rfork) {
545                                 (void)putchar('(');
546                                 rforkname((int)*ip);
547                                 ip++;
548                                 narg--;
549                                 c = ',';
550                         } else if (ktr->ktr_code == SYS_lio_listio) {
551                                 (void)putchar('(');
552                                 lio_listioname((int)*ip);
553                                 ip++;
554                                 narg--;
555                                 c = ',';
556                         } else if (ktr->ktr_code == SYS_mlockall) {
557                                 (void)putchar('(');
558                                 mlockallname((int)*ip);
559                                 ip++;
560                                 narg--;
561                         } else if (ktr->ktr_code == SYS_sched_setscheduler) {
562                                 print_number(ip,narg,c);
563                                 schedpolicyname((int)*ip);
564                                 ip++;
565                                 narg--;
566                         } else if (ktr->ktr_code == SYS_sched_get_priority_max ||
567                                    ktr->ktr_code == SYS_sched_get_priority_min) {
568                                 (void)putchar('(');
569                                 schedpolicyname((int)*ip);
570                                 ip++;
571                                 narg--;
572                         } else if (ktr->ktr_code == SYS_sendfile) {
573                                 print_number(ip,narg,c);
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                                 sendfileflagsname((int)*ip);
580                                 ip++;
581                                 narg--;
582                         } else if (ktr->ktr_code == SYS_kldsym) {
583                                 print_number(ip,narg,c);
584                                 kldsymcmdname((int)*ip);
585                                 ip++;
586                                 narg--;
587                         } else if (ktr->ktr_code == SYS_sigprocmask) {
588                                 (void)putchar('(');
589                                 sigprocmaskhowname((int)*ip);
590                                 ip++;
591                                 narg--;
592                                 c = ',';
593                         } else if (ktr->ktr_code == SYS___acl_get_file ||
594                                    ktr->ktr_code == SYS___acl_set_file ||
595                                    ktr->ktr_code == SYS___acl_get_fd ||
596                                    ktr->ktr_code == SYS___acl_set_fd ||
597                                    ktr->ktr_code == SYS___acl_delete_file ||
598                                    ktr->ktr_code == SYS___acl_delete_fd ||
599                                    ktr->ktr_code == SYS___acl_aclcheck_file ||
600                                    ktr->ktr_code == SYS___acl_aclcheck_fd) {
601                                 print_number(ip,narg,c);
602                                 acltypename((int)*ip);
603                                 ip++;
604                                 narg--;
605                         } else if (ktr->ktr_code == SYS_sigaction) {
606                                 (void)putchar('(');
607                                 signame((int)*ip);
608                                 ip++;
609                                 narg--;
610                                 c = ',';
611                         } else if (ktr->ktr_code == SYS_extattrctl) {
612                                 print_number(ip,narg,c);
613                                 extattrctlname((int)*ip);
614                                 ip++;
615                                 narg--;
616                         } else if (ktr->ktr_code == SYS_ptrace) {
617                                 if (*ip < sizeof(ptrace_ops) /
618                                     sizeof(ptrace_ops[0]) && *ip >= 0)
619                                         (void)printf("(%s", ptrace_ops[*ip]);
620 #ifdef PT_GETREGS
621                                 else if (*ip == PT_GETREGS)
622                                         (void)printf("(%s", "PT_GETREGS");
623 #endif
624 #ifdef PT_SETREGS
625                                 else if (*ip == PT_SETREGS)
626                                         (void)printf("(%s", "PT_SETREGS");
627 #endif
628 #ifdef PT_GETFPREGS
629                                 else if (*ip == PT_GETFPREGS)
630                                         (void)printf("(%s", "PT_GETFPREGS");
631 #endif
632 #ifdef PT_SETFPREGS
633                                 else if (*ip == PT_SETFPREGS)
634                                         (void)printf("(%s", "PT_SETFPREGS");
635 #endif
636 #ifdef PT_GETDBREGS
637                                 else if (*ip == PT_GETDBREGS)
638                                         (void)printf("(%s", "PT_GETDBREGS");
639 #endif
640 #ifdef PT_SETDBREGS
641                                 else if (*ip == PT_SETDBREGS)
642                                         (void)printf("(%s", "PT_SETDBREGS");
643 #endif
644                                 else
645                                         (void)printf("(%ld", (long)*ip);
646                                 c = ',';
647                                 ip++;
648                                 narg--;
649                         }
650                 }
651                 while (narg > 0) {
652                         print_number(ip,narg,c);
653                 }
654                 (void)putchar(')');
655         }
656         (void)putchar('\n');
657 }
658
659 ktrsysret(struct ktr_sysret *ktr)
660 {
661         register register_t ret = ktr->ktr_retval;
662         register int error = ktr->ktr_error;
663         register int code = ktr->ktr_code;
664
665         if (code >= nsyscalls || code < 0)
666                 (void)printf("[%d] ", code);
667         else
668                 (void)printf("%s ", syscallnames[code]);
669
670         if (error == 0) {
671                 if (fancy) {
672                         (void)printf("%d", ret);
673                         if (ret < 0 || ret > 9)
674                                 (void)printf("/%#lx", (long)ret);
675                 } else {
676                         if (decimal)
677                                 (void)printf("%ld", (long)ret);
678                         else
679                                 (void)printf("%#lx", (long)ret);
680                 }
681         } else if (error == ERESTART)
682                 (void)printf("RESTART");
683         else if (error == EJUSTRETURN)
684                 (void)printf("JUSTRETURN");
685         else {
686                 (void)printf("-1 errno %d", ktr->ktr_error);
687                 if (fancy)
688                         (void)printf(" %s", strerror(ktr->ktr_error));
689         }
690         (void)putchar('\n');
691 }
692
693 ktrnamei(char *cp, int len)
694 {
695         (void)printf("\"%.*s\"\n", len, cp);
696 }
697
698 ktrgenio(struct ktr_genio *ktr, int len)
699 {
700         register int datalen = len - sizeof (struct ktr_genio);
701         register char *dp = (char *)ktr + sizeof (struct ktr_genio);
702         register char *cp;
703         register int col = 0;
704         register width;
705         char visbuf[5];
706         static screenwidth = 0;
707
708         if (screenwidth == 0) {
709                 struct winsize ws;
710
711                 if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 &&
712                     ws.ws_col > 8)
713                         screenwidth = ws.ws_col;
714                 else
715                         screenwidth = 80;
716         }
717         printf("fd %d %s %d byte%s\n", ktr->ktr_fd,
718                 ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen,
719                 datalen == 1 ? "" : "s");
720         if (maxdata && datalen > maxdata)
721                 datalen = maxdata;
722         (void)printf("       \"");
723         col = 8;
724         for (;datalen > 0; datalen--, dp++) {
725                 (void) vis(visbuf, *dp, VIS_CSTYLE, *(dp+1));
726                 cp = visbuf;
727                 /*
728                  * Keep track of printables and
729                  * space chars (like fold(1)).
730                  */
731                 if (col == 0) {
732                         (void)putchar('\t');
733                         col = 8;
734                 }
735                 switch(*cp) {
736                 case '\n':
737                         col = 0;
738                         (void)putchar('\n');
739                         continue;
740                 case '\t':
741                         width = 8 - (col&07);
742                         break;
743                 default:
744                         width = strlen(cp);
745                 }
746                 if (col + width > (screenwidth-2)) {
747                         (void)printf("\\\n\t");
748                         col = 8;
749                 }
750                 col += width;
751                 do {
752                         (void)putchar(*cp++);
753                 } while (*cp);
754         }
755         if (col == 0)
756                 (void)printf("       ");
757         (void)printf("\"\n");
758 }
759
760 char *signames[NSIG] = {
761         "NULL", "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT",     /*  1 - 6  */
762         "EMT", "FPE", "KILL", "BUS", "SEGV", "SYS",             /*  7 - 12 */
763         "PIPE", "ALRM",  "TERM", "URG", "STOP", "TSTP",         /* 13 - 18 */
764         "CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU",           /* 19 - 24 */
765         "XFSZ", "VTALRM", "PROF", "WINCH", "29", "USR1",        /* 25 - 30 */
766         "USR2", NULL,                                           /* 31 - 32 */
767 };
768
769 ktrpsig(struct ktr_psig *psig)
770 {
771         (void)printf("SIG%s ", signames[psig->signo]);
772         if (psig->action == SIG_DFL)
773                 (void)printf("SIG_DFL\n");
774         else
775                 (void)printf("caught handler=0x%lx mask=0x%x code=0x%x\n",
776                     (u_long)psig->action, psig->mask, psig->code);
777 }
778
779 ktrcsw(struct ktr_csw *cs)
780 {
781         (void)printf("%s %s\n", cs->out ? "stop" : "resume",
782                 cs->user ? "user" : "kernel");
783 }
784
785 struct utrace_malloc {
786         void *p;
787         size_t s;
788         void *r;
789 };
790
791 void
792 ktruser_malloc(int len, unsigned char *p)
793 {
794         struct utrace_malloc *ut = (struct utrace_malloc *)p;
795
796         if (ut->p == NULL) {
797                 if (ut->s == 0 && ut->r == NULL)
798                         printf("malloc_init()\n");
799                 else
800                         printf("%p = malloc(%zu)\n", ut->r, ut->s);
801         } else {
802                 if (ut->s == 0)
803                         printf("free(%p)\n", ut->p);
804                 else
805                         printf("%p = realloc(%p, %zu)\n", ut->r, ut->p, ut->s);
806         }
807 }
808
809 ktruser(int len, unsigned char *p)
810 {
811         if (len == sizeof(struct utrace_malloc)) {
812                 ktruser_malloc(len, p);
813                 return;
814         }
815
816         (void)printf("%d ", len);
817         while (len--)
818                 (void)printf(" %02x", *p++);
819         (void)printf("\n");
820 }
821
822 usage(void)
823 {
824         (void)fprintf(stderr,
825             "usage: kdump [-dnlRT] [-f trfile] [-m maxdata] [-t [cnisuw]] [-p pid]\n");
826         exit(1);
827 }
828
829 timevalsub(struct timeval *t1, struct timeval *t2)
830 {
831         t1->tv_sec -= t2->tv_sec;
832         t1->tv_usec -= t2->tv_usec;
833         timevalfix(t1);
834 }
835
836 timevalfix(struct timeval *t1)
837 {
838         if (t1->tv_usec < 0) {
839                 t1->tv_sec--;
840                 t1->tv_usec += 1000000;
841         }
842         if (t1->tv_usec >= 1000000) {
843                 t1->tv_sec++;
844                 t1->tv_usec -= 1000000;
845         }
846 }