usched: Allow process to change self cpu affinity
[dragonfly.git] / usr.bin / kdump / kdump.c
blobc5344560837f383360e2888fec4f7ec8a1e6ae50
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 print_number(ip,narg,c);
314 putchar(',');
315 accessmodename ((int)*ip);
316 ip++;
317 narg--;
318 } else if (ktr->ktr_code == SYS_open ||
319 ktr->ktr_code == SYS_mq_open) {
320 int flags;
321 int mode;
322 print_number(ip,narg,c);
323 flags = *ip;
324 mode = *++ip;
325 putchar(',');
326 flagsandmodename (flags, mode, decimal);
327 ip++;
328 narg-=2;
329 } else if (ktr->ktr_code == SYS_wait4) {
330 print_number(ip,narg,c);
331 print_number(ip,narg,c);
332 putchar(',');
333 wait4optname ((int)*ip);
334 ip++;
335 narg--;
336 } else if (ktr->ktr_code == SYS_chmod ||
337 ktr->ktr_code == SYS_fchmod ||
338 ktr->ktr_code == SYS_lchmod) {
339 print_number(ip,narg,c);
340 putchar(',');
341 modename ((int)*ip);
342 ip++;
343 narg--;
344 } else if (ktr->ktr_code == SYS_mknod) {
345 print_number(ip,narg,c);
346 putchar(',');
347 modename ((int)*ip);
348 ip++;
349 narg--;
350 } else if (ktr->ktr_code == SYS_getfsstat) {
351 print_number(ip,narg,c);
352 print_number(ip,narg,c);
353 putchar(',');
354 getfsstatflagsname ((int)*ip);
355 ip++;
356 narg--;
357 } else if (ktr->ktr_code == SYS_mount) {
358 print_number(ip,narg,c);
359 print_number(ip,narg,c);
360 putchar(',');
361 mountflagsname ((int)*ip);
362 ip++;
363 narg--;
364 } else if (ktr->ktr_code == SYS_unmount) {
365 print_number(ip,narg,c);
366 putchar(',');
367 mountflagsname ((int)*ip);
368 ip++;
369 narg--;
370 } else if (ktr->ktr_code == SYS_recvmsg ||
371 ktr->ktr_code == SYS_sendmsg) {
372 print_number(ip,narg,c);
373 print_number(ip,narg,c);
374 putchar(',');
375 sendrecvflagsname ((int)*ip);
376 ip++;
377 narg--;
378 } else if (ktr->ktr_code == SYS_recvfrom ||
379 ktr->ktr_code == SYS_sendto) {
380 print_number(ip,narg,c);
381 print_number(ip,narg,c);
382 print_number(ip,narg,c);
383 putchar(',');
384 sendrecvflagsname ((int)*ip);
385 ip++;
386 narg--;
387 } else if (ktr->ktr_code == SYS_chflags ||
388 ktr->ktr_code == SYS_fchflags) {
389 print_number(ip,narg,c);
390 putchar(',');
391 modename((int)*ip);
392 ip++;
393 narg--;
394 } else if (ktr->ktr_code == SYS_kill) {
395 print_number(ip,narg,c);
396 putchar(',');
397 signame((int)*ip);
398 ip++;
399 narg--;
400 } else if (ktr->ktr_code == SYS_reboot) {
401 putchar('(');
402 rebootoptname((int)*ip);
403 ip++;
404 narg--;
405 } else if (ktr->ktr_code == SYS_umask) {
406 putchar('(');
407 modename((int)*ip);
408 ip++;
409 narg--;
410 } else if (ktr->ktr_code == SYS_msync) {
411 print_number(ip,narg,c);
412 print_number(ip,narg,c);
413 putchar(',');
414 msyncflagsname((int)*ip);
415 ip++;
416 narg--;
417 } else if (ktr->ktr_code == SYS_mmap) {
418 print_number(ip,narg,c);
419 print_number(ip,narg,c);
420 putchar(',');
421 mmapprotname ((int)*ip);
422 putchar(',');
423 ip++;
424 narg--;
425 mmapflagsname ((int)*ip);
426 ip++;
427 narg--;
428 } else if (ktr->ktr_code == SYS_mprotect) {
429 print_number(ip,narg,c);
430 print_number(ip,narg,c);
431 putchar(',');
432 mmapprotname ((int)*ip);
433 ip++;
434 narg--;
435 } else if (ktr->ktr_code == SYS_madvise) {
436 print_number(ip,narg,c);
437 print_number(ip,narg,c);
438 putchar(',');
439 madvisebehavname((int)*ip);
440 ip++;
441 narg--;
442 } else if (ktr->ktr_code == SYS_setpriority) {
443 putchar('(');
444 prioname((int)*ip);
445 ip++;
446 narg--;
447 c = ',';
448 print_number(ip,narg,c);
449 print_number(ip,narg,c);
450 } else if (ktr->ktr_code == SYS_fcntl) {
451 int cmd;
452 int arg;
453 print_number(ip,narg,c);
454 cmd = *ip;
455 arg = *++ip;
456 putchar(',');
457 fcntlcmdname(cmd, arg, decimal);
458 ip++;
459 narg-=2;
460 } else if (ktr->ktr_code == SYS_socket) {
461 putchar('(');
462 sockdomainname((int)*ip);
463 ip++;
464 narg--;
465 putchar(',');
466 socktypename((int)*ip);
467 ip++;
468 narg--;
469 c = ',';
470 } else if (ktr->ktr_code == SYS_setsockopt ||
471 ktr->ktr_code == SYS_getsockopt) {
472 print_number(ip,narg,c);
473 putchar(',');
474 sockoptlevelname((int)*ip, decimal);
475 ip++;
476 narg--;
477 putchar(',');
478 sockoptname((int)*ip);
479 ip++;
480 narg--;
481 } else if (ktr->ktr_code == SYS_lseek) {
482 print_number(ip,narg,c);
483 /* Hidden 'pad' argument, not in lseek(2) */
484 print_number(ip,narg,c);
485 print_number(ip,narg,c);
486 putchar(',');
487 whencename ((int)*ip);
488 ip++;
489 narg--;
490 } else if (ktr->ktr_code == SYS_flock) {
491 print_number(ip,narg,c);
492 putchar(',');
493 flockname((int)*ip);
494 ip++;
495 narg--;
496 } else if (ktr->ktr_code == SYS_mkfifo ||
497 ktr->ktr_code == SYS_mkdir) {
498 print_number(ip,narg,c);
499 putchar(',');
500 modename((int)*ip);
501 ip++;
502 narg--;
503 } else if (ktr->ktr_code == SYS_shutdown) {
504 print_number(ip,narg,c);
505 putchar(',');
506 shutdownhowname((int)*ip);
507 ip++;
508 narg--;
509 } else if (ktr->ktr_code == SYS_socketpair) {
510 putchar('(');
511 sockdomainname((int)*ip);
512 ip++;
513 narg--;
514 putchar(',');
515 socktypename((int)*ip);
516 ip++;
517 narg--;
518 c = ',';
519 } else if (ktr->ktr_code == SYS_getrlimit ||
520 ktr->ktr_code == SYS_setrlimit) {
521 putchar('(');
522 rlimitname((int)*ip);
523 ip++;
524 narg--;
525 c = ',';
526 } else if (ktr->ktr_code == SYS_quotactl) {
527 print_number(ip,narg,c);
528 quotactlname((int)*ip);
529 ip++;
530 narg--;
531 c = ',';
532 } else if (ktr->ktr_code == SYS_rtprio) {
533 putchar('(');
534 rtprioname((int)*ip);
535 ip++;
536 narg--;
537 c = ',';
538 } else if (ktr->ktr_code == SYS___semctl) {
539 print_number(ip,narg,c);
540 print_number(ip,narg,c);
541 semctlname((int)*ip);
542 ip++;
543 narg--;
544 } else if (ktr->ktr_code == SYS_semget) {
545 print_number(ip,narg,c);
546 print_number(ip,narg,c);
547 semgetname((int)*ip);
548 ip++;
549 narg--;
550 } else if (ktr->ktr_code == SYS_msgctl) {
551 print_number(ip,narg,c);
552 shmctlname((int)*ip);
553 ip++;
554 narg--;
555 } else if (ktr->ktr_code == SYS_shmat) {
556 print_number(ip,narg,c);
557 print_number(ip,narg,c);
558 shmatname((int)*ip);
559 ip++;
560 narg--;
561 } else if (ktr->ktr_code == SYS_shmctl) {
562 print_number(ip,narg,c);
563 shmctlname((int)*ip);
564 ip++;
565 narg--;
566 } else if (ktr->ktr_code == SYS_minherit) {
567 print_number(ip,narg,c);
568 print_number(ip,narg,c);
569 minheritname((int)*ip);
570 ip++;
571 narg--;
572 } else if (ktr->ktr_code == SYS_rfork) {
573 putchar('(');
574 rforkname((int)*ip);
575 ip++;
576 narg--;
577 c = ',';
578 } else if (ktr->ktr_code == SYS_lio_listio) {
579 putchar('(');
580 lio_listioname((int)*ip);
581 ip++;
582 narg--;
583 c = ',';
584 } else if (ktr->ktr_code == SYS_mlockall) {
585 putchar('(');
586 mlockallname((int)*ip);
587 ip++;
588 narg--;
589 } else if (ktr->ktr_code == SYS_sched_setscheduler) {
590 print_number(ip,narg,c);
591 schedpolicyname((int)*ip);
592 ip++;
593 narg--;
594 } else if (ktr->ktr_code == SYS_sched_get_priority_max ||
595 ktr->ktr_code == SYS_sched_get_priority_min) {
596 putchar('(');
597 schedpolicyname((int)*ip);
598 ip++;
599 narg--;
600 } else if (ktr->ktr_code == SYS_sendfile) {
601 print_number(ip,narg,c);
602 print_number(ip,narg,c);
603 print_number(ip,narg,c);
604 print_number(ip,narg,c);
605 print_number(ip,narg,c);
606 print_number(ip,narg,c);
607 sendfileflagsname((int)*ip);
608 ip++;
609 narg--;
610 } else if (ktr->ktr_code == SYS_kldsym) {
611 print_number(ip,narg,c);
612 kldsymcmdname((int)*ip);
613 ip++;
614 narg--;
615 } else if (ktr->ktr_code == SYS_sigprocmask) {
616 putchar('(');
617 sigprocmaskhowname((int)*ip);
618 ip++;
619 narg--;
620 c = ',';
621 } else if (ktr->ktr_code == SYS___acl_get_file ||
622 ktr->ktr_code == SYS___acl_set_file ||
623 ktr->ktr_code == SYS___acl_get_fd ||
624 ktr->ktr_code == SYS___acl_set_fd ||
625 ktr->ktr_code == SYS___acl_delete_file ||
626 ktr->ktr_code == SYS___acl_delete_fd ||
627 ktr->ktr_code == SYS___acl_aclcheck_file ||
628 ktr->ktr_code == SYS___acl_aclcheck_fd) {
629 print_number(ip,narg,c);
630 acltypename((int)*ip);
631 ip++;
632 narg--;
633 } else if (ktr->ktr_code == SYS_sigaction) {
634 putchar('(');
635 signame((int)*ip);
636 ip++;
637 narg--;
638 c = ',';
639 } else if (ktr->ktr_code == SYS_extattrctl) {
640 print_number(ip,narg,c);
641 extattrctlname((int)*ip);
642 ip++;
643 narg--;
644 } else if (ktr->ktr_code == SYS_ptrace) {
645 if (*ip < (register_t)(sizeof(ptrace_ops) /
646 sizeof(ptrace_ops[0])) && *ip >= 0)
647 printf("(%s", ptrace_ops[*ip]);
648 #ifdef PT_GETREGS
649 else if (*ip == PT_GETREGS)
650 printf("(%s", "PT_GETREGS");
651 #endif
652 #ifdef PT_SETREGS
653 else if (*ip == PT_SETREGS)
654 printf("(%s", "PT_SETREGS");
655 #endif
656 #ifdef PT_GETFPREGS
657 else if (*ip == PT_GETFPREGS)
658 printf("(%s", "PT_GETFPREGS");
659 #endif
660 #ifdef PT_SETFPREGS
661 else if (*ip == PT_SETFPREGS)
662 printf("(%s", "PT_SETFPREGS");
663 #endif
664 #ifdef PT_GETDBREGS
665 else if (*ip == PT_GETDBREGS)
666 printf("(%s", "PT_GETDBREGS");
667 #endif
668 #ifdef PT_SETDBREGS
669 else if (*ip == PT_SETDBREGS)
670 printf("(%s", "PT_SETDBREGS");
671 #endif
672 else
673 printf("(%ld", (long)*ip);
674 c = ',';
675 ip++;
676 narg--;
679 while (narg > 0) {
680 print_number(ip,narg,c);
682 putchar(')');
684 putchar('\n');
687 static void
688 ktrsysret(struct ktr_sysret *ktr)
690 register_t ret = ktr->ktr_retval;
691 int error = ktr->ktr_error;
692 int code = ktr->ktr_code;
694 if (code >= nsyscalls || code < 0)
695 printf("[%d] ", code);
696 else
697 printf("%s ", syscallnames[code]);
699 if (error == 0) {
700 if (fancy) {
701 printf("%ld", (long)ret);
702 if (ret < 0 || ret > 9)
703 printf("/%#lx", (long)ret);
704 } else {
705 if (decimal)
706 printf("%ld", (long)ret);
707 else
708 printf("%#lx", (long)ret);
710 } else if (error == ERESTART)
711 printf("RESTART");
712 else if (error == EJUSTRETURN)
713 printf("JUSTRETURN");
714 else {
715 printf("-1 errno %d", ktr->ktr_error);
716 if (fancy)
717 printf(" %s", strerror(ktr->ktr_error));
719 putchar('\n');
722 static void
723 ktrnamei(char *cp, int len)
725 printf("\"%.*s\"\n", len, cp);
728 static void
729 ktrgenio(struct ktr_genio *ktr, int len)
731 int datalen = len - sizeof (struct ktr_genio);
732 char *dp = (char *)ktr + sizeof (struct ktr_genio);
733 char *cp;
734 int col = 0;
735 int width;
736 char visbuf[5];
737 static int screenwidth = 0;
739 if (screenwidth == 0) {
740 struct winsize ws;
742 if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 &&
743 ws.ws_col > 8)
744 screenwidth = ws.ws_col;
745 else
746 screenwidth = 80;
748 printf("fd %d %s %d byte%s\n", ktr->ktr_fd,
749 ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen,
750 datalen == 1 ? "" : "s");
751 if (maxdata && datalen > maxdata)
752 datalen = maxdata;
753 printf(" \"");
754 col = 8;
755 for (;datalen > 0; datalen--, dp++) {
756 vis(visbuf, *dp, VIS_CSTYLE, *(dp+1));
757 cp = visbuf;
759 * Keep track of printables and
760 * space chars (like fold(1)).
762 if (col == 0) {
763 putchar('\t');
764 col = 8;
766 switch(*cp) {
767 case '\n':
768 col = 0;
769 putchar('\n');
770 continue;
771 case '\t':
772 width = 8 - (col&07);
773 break;
774 default:
775 width = strlen(cp);
777 if (col + width > (screenwidth-2)) {
778 printf("\\\n\t");
779 col = 8;
781 col += width;
782 do {
783 putchar(*cp++);
784 } while (*cp);
786 if (col == 0)
787 printf(" ");
788 printf("\"\n");
791 const char *signames[NSIG] = {
792 "NULL", "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT", /* 1 - 6 */
793 "EMT", "FPE", "KILL", "BUS", "SEGV", "SYS", /* 7 - 12 */
794 "PIPE", "ALRM", "TERM", "URG", "STOP", "TSTP", /* 13 - 18 */
795 "CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU", /* 19 - 24 */
796 "XFSZ", "VTALRM", "PROF", "WINCH", "29", "USR1", /* 25 - 30 */
797 "USR2", NULL, /* 31 - 32 */
800 static void
801 ktrpsig(struct ktr_psig *psig)
803 printf("SIG%s ", signames[psig->signo]);
804 if (psig->action == SIG_DFL)
805 printf("SIG_DFL\n");
806 else
807 printf("caught handler=0x%lx mask=0x%x code=0x%x\n",
808 (u_long)psig->action, psig->mask.__bits[0], psig->code);
811 static void
812 ktrcsw(struct ktr_csw *cs)
814 printf("%s %s\n", cs->out ? "stop" : "resume",
815 cs->user ? "user" : "kernel");
818 #define UTRACE_DLOPEN_START 1
819 #define UTRACE_DLOPEN_STOP 2
820 #define UTRACE_DLCLOSE_START 3
821 #define UTRACE_DLCLOSE_STOP 4
822 #define UTRACE_LOAD_OBJECT 5
823 #define UTRACE_UNLOAD_OBJECT 6
824 #define UTRACE_ADD_RUNDEP 7
825 #define UTRACE_PRELOAD_FINISHED 8
826 #define UTRACE_INIT_CALL 9
827 #define UTRACE_FINI_CALL 10
829 struct utrace_rtld {
830 char sig[4]; /* 'RTLD' */
831 int event;
832 void *handle;
833 void *mapbase;
834 size_t mapsize;
835 int refcnt;
836 char name[MAXPATHLEN];
839 static void
840 ktruser_rtld(int len, unsigned char *p)
842 struct utrace_rtld *ut = (struct utrace_rtld *)p;
843 void *parent;
844 int mode;
846 switch (ut->event) {
847 case UTRACE_DLOPEN_START:
848 mode = ut->refcnt;
849 printf("dlopen(%s, ", ut->name);
850 switch (mode & RTLD_MODEMASK) {
851 case RTLD_NOW:
852 printf("RTLD_NOW");
853 break;
854 case RTLD_LAZY:
855 printf("RTLD_LAZY");
856 break;
857 default:
858 printf("%#x", mode & RTLD_MODEMASK);
860 if (mode & RTLD_GLOBAL)
861 printf(" | RTLD_GLOBAL");
862 if (mode & RTLD_TRACE)
863 printf(" | RTLD_TRACE");
864 if (mode & ~(RTLD_MODEMASK | RTLD_GLOBAL | RTLD_TRACE))
865 printf(" | %#x", mode &
866 ~(RTLD_MODEMASK | RTLD_GLOBAL | RTLD_TRACE));
867 printf(")\n");
868 break;
869 case UTRACE_DLOPEN_STOP:
870 printf("%p = dlopen(%s) ref %d\n", ut->handle, ut->name,
871 ut->refcnt);
872 break;
873 case UTRACE_DLCLOSE_START:
874 printf("dlclose(%p) (%s, %d)\n", ut->handle, ut->name,
875 ut->refcnt);
876 break;
877 case UTRACE_DLCLOSE_STOP:
878 printf("dlclose(%p) finished\n", ut->handle);
879 break;
880 case UTRACE_LOAD_OBJECT:
881 printf("RTLD: loaded %p @ %p - %p (%s)\n", ut->handle,
882 ut->mapbase, (char *)ut->mapbase + ut->mapsize - 1,
883 ut->name);
884 break;
885 case UTRACE_UNLOAD_OBJECT:
886 printf("RTLD: unloaded %p @ %p - %p (%s)\n", ut->handle,
887 ut->mapbase, (char *)ut->mapbase + ut->mapsize - 1,
888 ut->name);
889 break;
890 case UTRACE_ADD_RUNDEP:
891 parent = ut->mapbase;
892 printf("RTLD: %p now depends on %p (%s, %d)\n", parent,
893 ut->handle, ut->name, ut->refcnt);
894 break;
895 case UTRACE_PRELOAD_FINISHED:
896 printf("RTLD: LD_PRELOAD finished\n");
897 break;
898 case UTRACE_INIT_CALL:
899 printf("RTLD: init %p for %p (%s)\n", ut->mapbase, ut->handle,
900 ut->name);
901 break;
902 case UTRACE_FINI_CALL:
903 printf("RTLD: fini %p for %p (%s)\n", ut->mapbase, ut->handle,
904 ut->name);
905 break;
906 default:
907 p += 4;
908 len -= 4;
909 printf("RTLD: %d ", len);
910 while (len--)
911 if (decimal)
912 printf(" %d", *p++);
913 else
914 printf(" %02x", *p++);
915 printf("\n");
919 struct utrace_malloc {
920 void *p;
921 size_t s;
922 void *r;
925 static void
926 ktruser_malloc(int len __unused, unsigned char *p)
928 struct utrace_malloc *ut = (struct utrace_malloc *)p;
930 if (ut->p == NULL) {
931 if (ut->s == 0 && ut->r == NULL)
932 printf("malloc_init()\n");
933 else
934 printf("%p = malloc(%zu)\n", ut->r, ut->s);
935 } else {
936 if (ut->s == 0)
937 printf("free(%p)\n", ut->p);
938 else
939 printf("%p = realloc(%p, %zu)\n", ut->r, ut->p, ut->s);
943 static void
944 ktruser(int len, unsigned char *p)
947 if (len >= 8 && bcmp(p, "RTLD", 4) == 0) {
948 ktruser_rtld(len, p);
949 return;
952 if (len == sizeof(struct utrace_malloc)) {
953 ktruser_malloc(len, p);
954 return;
957 printf("%d ", len);
958 while (len--)
959 printf(" %02x", *p++);
960 printf("\n");
963 static void
964 usage(void)
966 fprintf(stderr,
967 "usage: kdump [-dnlRT] [-f trfile] [-m maxdata] [-t [cnisuw]] [-p pid]\n");
968 exit(1);
971 static void
972 timevalsub(struct timeval *t1, struct timeval *t2)
974 t1->tv_sec -= t2->tv_sec;
975 t1->tv_usec -= t2->tv_usec;
976 timevalfix(t1);
979 static void
980 timevalfix(struct timeval *t1)
982 if (t1->tv_usec < 0) {
983 t1->tv_sec--;
984 t1->tv_usec += 1000000;
986 if (t1->tv_usec >= 1000000) {
987 t1->tv_sec++;
988 t1->tv_usec -= 1000000;