]> git.saurik.com Git - apple/system_cmds.git/blob - kdump.tproj/kdump.c
system_cmds-336.23.tar.gz
[apple/system_cmds.git] / kdump.tproj / kdump.c
1 /*
2 * Copyright (c) 1999, 2000-2001 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License."
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24 /*-
25 * Copyright (c) 1988, 1993
26 * The Regents of the University of California. All rights reserved.
27 *
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
30 * are met:
31 * 1. Redistributions of source code must retain the above copyright
32 * notice, this list of conditions and the following disclaimer.
33 * 2. Redistributions in binary form must reproduce the above copyright
34 * notice, this list of conditions and the following disclaimer in the
35 * documentation and/or other materials provided with the distribution.
36 * 3. All advertising materials mentioning features or use of this software
37 * must display the following acknowledgement:
38 * This product includes software developed by the University of
39 * California, Berkeley and its contributors.
40 * 4. Neither the name of the University nor the names of its contributors
41 * may be used to endorse or promote products derived from this software
42 * without specific prior written permission.
43 *
44 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54 * SUCH DAMAGE.
55 */
56 #include <sys/cdefs.h>
57
58 #ifndef lint
59 __unused static const char copyright[] =
60 "@(#) Copyright (c) 1988, 1993\n\
61 The Regents of the University of California. All rights reserved.\n";
62 #endif /* not lint */
63
64 #ifndef lint
65 #if 0
66 __unused static char sccsid[] = "@(#)kdump.c 8.1 (Berkeley) 6/6/93";
67 #endif
68 __unused static const char rcsid[] =
69 "$FreeBSD: src/usr.bin/kdump/kdump.c,v 1.17 1999/12/29 05:05:33 peter Exp $";
70 #endif /* not lint */
71
72 #include <errno.h>
73 #include <sys/param.h>
74 #include <sys/errno.h>
75 #include <sys/time.h>
76 #include <sys/uio.h>
77 #include <sys/ktrace.h>
78 #include <sys/ioctl.h>
79 #include <sys/ptrace.h>
80 #include <err.h>
81 #include <locale.h>
82 #include <stdio.h>
83 #include <stdlib.h>
84 #include <string.h>
85 #include <unistd.h>
86 #include <vis.h>
87 #include "ktrace.h"
88
89 #define ERESTART -1
90 #define EJUSTRETURN -2
91 int timestamp, decimal, fancy = 1, tail, maxdata;
92 char *tracefile = DEF_TRACEFILE;
93 struct ktr_header ktr_header;
94
95 #define eqs(s1, s2) (strcmp((s1), (s2)) == 0)
96
97 /* Forward declarations */
98 void usage(void);
99 int fread_tail(char *buf, int size, int num);
100 void dumpheader(struct ktr_header *kth);
101 void dumpheader(struct ktr_header *kth);
102 void ktrsyscall(struct ktr_syscall *ktr);
103 void ktrsysret(struct ktr_sysret *ktr);
104 void ktrnamei(char *cp, int len);
105 void ktrgenio(struct ktr_genio *ktr, int len);
106 void ktrpsig(struct ktr_psig *psig);
107 void ktrcsw(struct ktr_csw *cs);
108 void ktruser(int len, unsigned char *p);
109
110 int
111 main(int argc, char *argv[])
112 {
113 int ch, ktrlen, size;
114 void *m;
115 int trpoints = ALL_POINTS;
116
117 (void) setlocale(LC_CTYPE, "");
118
119 while ((ch = getopt(argc,argv,"f:dlm:nRTt:")) != -1)
120 switch((char)ch) {
121 case 'f':
122 tracefile = optarg;
123 break;
124 case 'd':
125 decimal = 1;
126 break;
127 case 'l':
128 tail = 1;
129 break;
130 case 'm':
131 maxdata = atoi(optarg);
132 break;
133 case 'n':
134 fancy = 0;
135 break;
136 case 'R':
137 timestamp = 2; /* relative timestamp */
138 break;
139 case 'T':
140 timestamp = 1;
141 break;
142 case 't':
143 trpoints = getpoints(optarg);
144 if (trpoints < 0)
145 errx(1, "unknown trace point in %s", optarg);
146 break;
147 default:
148 usage();
149 }
150
151 if (argc > optind)
152 usage();
153
154 m = (void *)malloc(size = 1025);
155 if (m == NULL)
156 errx(1, "%s", strerror(ENOMEM));
157 if (!freopen(tracefile, "r", stdin))
158 err(1, "%s", tracefile);
159 while (fread_tail((char *)&ktr_header, sizeof(struct ktr_header), 1)) {
160 if (trpoints & (1<<ktr_header.ktr_type))
161 dumpheader(&ktr_header);
162 if ((ktrlen = ktr_header.ktr_len) < 0)
163 errx(1, "bogus length 0x%x", ktrlen);
164 if (ktrlen > size) {
165 m = (void *)realloc(m, ktrlen+1);
166 if (m == NULL)
167 errx(1, "%s", strerror(ENOMEM));
168 size = ktrlen;
169 }
170 if (ktrlen && fread_tail(m, ktrlen, 1) == 0)
171 errx(1, "data too short");
172 if ((trpoints & (1<<ktr_header.ktr_type)) == 0)
173 continue;
174 switch (ktr_header.ktr_type) {
175 case KTR_SYSCALL:
176 ktrsyscall((struct ktr_syscall *)m);
177 break;
178 case KTR_SYSRET:
179 ktrsysret((struct ktr_sysret *)m);
180 break;
181 case KTR_NAMEI:
182 ktrnamei(m, ktrlen);
183 break;
184 case KTR_GENIO:
185 ktrgenio((struct ktr_genio *)m, ktrlen);
186 break;
187 case KTR_PSIG:
188 ktrpsig((struct ktr_psig *)m);
189 break;
190 case KTR_CSW:
191 ktrcsw((struct ktr_csw *)m);
192 break;
193 case KTR_USER:
194 ktruser(ktrlen, m);
195 break;
196 }
197 if (tail)
198 (void)fflush(stdout);
199 }
200
201 return 0;
202 }
203
204 int
205 fread_tail(char *buf, int size, int num)
206 {
207 int i;
208
209 while ((i = fread(buf, size, num, stdin)) == 0 && tail) {
210 (void)sleep(1);
211 clearerr(stdin);
212 }
213 return (i);
214 }
215
216 void
217 dumpheader(struct ktr_header *kth)
218 {
219 static char unknown[64];
220 static struct timeval prevtime, temp;
221 char *type;
222
223 switch (kth->ktr_type) {
224 case KTR_SYSCALL:
225 type = "CALL";
226 break;
227 case KTR_SYSRET:
228 type = "RET ";
229 break;
230 case KTR_NAMEI:
231 type = "NAMI";
232 break;
233 case KTR_GENIO:
234 type = "GIO ";
235 break;
236 case KTR_PSIG:
237 type = "PSIG";
238 break;
239 case KTR_CSW:
240 type = "CSW";
241 break;
242 case KTR_USER:
243 type = "USER";
244 break;
245 default:
246 (void)sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type);
247 type = unknown;
248 }
249
250 (void)printf("%6d %-8.*s ", kth->ktr_pid, MAXCOMLEN, kth->ktr_comm);
251 if (timestamp) {
252 if (timestamp == 2) {
253 temp = kth->ktr_time;
254 timevalsub(&kth->ktr_time, &prevtime);
255 prevtime = temp;
256 }
257 (void)printf("%ld.%06d ",
258 kth->ktr_time.tv_sec, kth->ktr_time.tv_usec);
259 }
260 (void)printf("%s ", type);
261 }
262
263 #include <sys/syscall.h>
264 #include "syscalls.c"
265 int nsyscalls = sizeof (syscallnames) / sizeof (syscallnames[0]);
266
267 static 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",
271 "PT_SIGEXC", "PT_THUPDATE", "PT_ATTACHEXC",
272 };
273
274 void
275 ktrsyscall(struct ktr_syscall *ktr)
276 {
277 register_t narg = ktr->ktr_narg;
278 unsigned long long *ip;
279 char *ioctlname();
280
281 if (ktr->ktr_code >= nsyscalls || ktr->ktr_code < 0)
282 (void)printf("[%d]", ktr->ktr_code);
283 else
284 (void)printf("%s", syscallnames[ktr->ktr_code]);
285 ip = &ktr->ktr_args[0];
286 if (narg) {
287 char c = '(';
288 if (fancy) {
289 if (ktr->ktr_code == SYS_ioctl) {
290 char *cp;
291 if (decimal)
292 (void)printf("(%ld", (long)*ip);
293 else
294 (void)printf("(%#lx", (long)*ip);
295 ip++;
296 narg--;
297 if ((cp = ioctlname(*ip)) != NULL)
298 (void)printf(",%s", cp);
299 else {
300 if (decimal)
301 (void)printf(",%ld", (long)*ip);
302 else
303 (void)printf(",%#lx ", (long)*ip);
304 }
305 c = ',';
306 ip++;
307 narg--;
308 } else if (ktr->ktr_code == SYS_ptrace) {
309 if (*ip < sizeof(ptrace_ops) /
310 sizeof(ptrace_ops[0]) && *ip >= 0)
311 (void)printf("(%s", ptrace_ops[*ip]);
312 #ifdef PT_FORCEQUOTA
313 else if (*ip == PT_FORCEQUOTA)
314 (void)printf("(%s", "PT_FORCEQUOTA");
315 #endif
316 #ifdef PT_DENY_ATTACH
317 else if (*ip == PT_DENY_ATTACH)
318 (void)printf("(%s", "PT_DENY_ATTACH");
319 #endif
320 #ifdef PT_FIRSTMACH
321 else if (*ip == PT_FIRSTMACH)
322 (void)printf("(%s", "PT_FIRSTMACH");
323 #endif
324 else
325 (void)printf("(%ld", (long)*ip);
326 c = ',';
327 ip++;
328 narg--;
329 }
330 }
331 while (narg) {
332 if (decimal)
333 (void)printf("%c%ld", c, (long)*ip);
334 else
335 (void)printf("%c%#lx", c, (long)*ip);
336 c = ',';
337 ip++;
338 narg--;
339 }
340 (void)putchar(')');
341 }
342 (void)putchar('\n');
343 }
344
345 void
346 ktrsysret(struct ktr_sysret *ktr)
347 {
348 register_t ret = ktr->ktr_retval;
349 int error = ktr->ktr_error;
350 int code = ktr->ktr_code;
351
352 if (code >= nsyscalls || code < 0)
353 (void)printf("[%d] ", code);
354 else
355 (void)printf("%s ", syscallnames[code]);
356
357 if (error == 0) {
358 if (fancy) {
359 (void)printf("%d", ret);
360 if (ret < 0 || ret > 9)
361 (void)printf("/%#lx", (long)ret);
362 } else {
363 if (decimal)
364 (void)printf("%ld", (long)ret);
365 else
366 (void)printf("%#lx", (long)ret);
367 }
368 } else if (error == ERESTART)
369 (void)printf("RESTART");
370 else if (error == EJUSTRETURN)
371 (void)printf("JUSTRETURN");
372 else {
373 (void)printf("-1 errno %d", ktr->ktr_error);
374 if (fancy)
375 (void)printf(" %s", strerror(ktr->ktr_error));
376 }
377 (void)putchar('\n');
378 }
379
380 void
381 ktrnamei(char *cp, int len)
382 {
383 (void)printf("\"%.*s\"\n", len, cp);
384 }
385
386 void
387 ktrgenio(struct ktr_genio *ktr, int len)
388 {
389 int datalen = len - sizeof (struct ktr_genio);
390 char *dp = (char *)ktr + sizeof (struct ktr_genio);
391 char *cp;
392 int col = 0;
393 int width;
394 char visbuf[5];
395 static int screenwidth = 0;
396
397 if (screenwidth == 0) {
398 struct winsize ws;
399
400 if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 &&
401 ws.ws_col > 8)
402 screenwidth = ws.ws_col;
403 else
404 screenwidth = 80;
405 }
406 printf("fd %d %s %d byte%s\n", ktr->ktr_fd,
407 ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen,
408 datalen == 1 ? "" : "s");
409 if (maxdata && datalen > maxdata)
410 datalen = maxdata;
411 (void)printf(" \"");
412 col = 8;
413 for (;datalen > 0; datalen--, dp++) {
414 (void) vis(visbuf, *dp, VIS_CSTYLE, *(dp+1));
415 cp = visbuf;
416 /*
417 * Keep track of printables and
418 * space chars (like fold(1)).
419 */
420 if (col == 0) {
421 (void)putchar('\t');
422 col = 8;
423 }
424 switch(*cp) {
425 case '\n':
426 col = 0;
427 (void)putchar('\n');
428 continue;
429 case '\t':
430 width = 8 - (col&07);
431 break;
432 default:
433 width = strlen(cp);
434 }
435 if (col + width > (screenwidth-2)) {
436 (void)printf("\\\n\t");
437 col = 8;
438 }
439 col += width;
440 do {
441 (void)putchar(*cp++);
442 } while (*cp);
443 }
444 if (col == 0)
445 (void)printf(" ");
446 (void)printf("\"\n");
447 }
448
449 char *signames[] = {
450 "NULL", "HUP", "INT", "QUIT", "ILL", "TRAP", "ABRT", /* 1 - 6 */
451 "EMT", "FPE", "KILL", "BUS", "SEGV", "SYS", /* 7 - 12 */
452 "PIPE", "ALRM", "TERM", "URG", "STOP", "TSTP", /* 13 - 18 */
453 "CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU", /* 19 - 24 */
454 "XFSZ", "VTALRM", "PROF", "WINCH", "INFO", "USR1", /* 25 - 30 */
455 "USR2", NULL, /* 31 - 32 */
456 };
457
458 void
459 ktrpsig(struct ktr_psig *psig)
460 {
461 (void)printf("SIG%s ", signames[psig->signo]);
462 if (psig->action == SIG_DFL)
463 (void)printf("SIG_DFL\n");
464 else
465 (void)printf("caught handler=0x%lx mask=0x%x code=0x%x\n",
466 (u_long)psig->action, psig->mask, psig->code);
467 }
468
469 void
470 ktrcsw(struct ktr_csw *cs)
471 {
472 (void)printf("%s %s\n", cs->out ? "stop" : "resume",
473 cs->user ? "user" : "kernel");
474 }
475
476 void
477 ktruser(int len, unsigned char *p)
478 {
479 (void)printf("%d ", len);
480 while (len--)
481 (void)printf(" %02x", *p++);
482 (void)printf("\n");
483
484 }
485
486 void
487 usage(void)
488 {
489 (void)fprintf(stderr,
490 "usage: kdump [-dnlRT] [-f trfile] [-m maxdata] [-t [cnisuw]]\n");
491 exit(1);
492 }