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