1 /*-
2 * Copyright (c) 1988, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8 #ifndef lint
9 static char copyright[] =
10 "@(#) Copyright (c) 1988, 1993\n\
11 The Regents of the University of California. All rights reserved.\n";
12 #endif /* not lint */
13
14 #ifndef lint
15 static char sccsid[] = "@(#)kdump.c 8.4 (Berkeley) 04/28/95";
16 #endif /* not lint */
17
18 #include <sys/param.h>
19 #include <sys/errno.h>
20 #include <sys/time.h>
21 #include <sys/uio.h>
22 #include <sys/ktrace.h>
23 #include <sys/ioctl.h>
24 #include <sys/ptrace.h>
25 #define KERNEL
26 #include <sys/errno.h>
27 #undef KERNEL
28
29 #include <err.h>
30 #include <signal.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <unistd.h>
35 #include <vis.h>
36
37 #include "ktrace.h"
38
39 int timestamp, decimal, fancy = 1, tail, maxdata;
40 char *tracefile = DEF_TRACEFILE;
41 struct ktr_header ktr_header;
42
43 #define eqs(s1, s2) (strcmp((s1), (s2)) == 0)
44
45 int
main(argc,argv)46 main(argc, argv)
47 int argc;
48 char *argv[];
49 {
50 int ch, ktrlen, size;
51 register void *m;
52 int trpoints = ALL_POINTS;
53
54 while ((ch = getopt(argc, argv, "f:dlm:nRTt:")) != -1)
55 switch (ch) {
56 case 'f':
57 tracefile = optarg;
58 break;
59 case 'd':
60 decimal = 1;
61 break;
62 case 'l':
63 tail = 1;
64 break;
65 case 'm':
66 maxdata = atoi(optarg);
67 break;
68 case 'n':
69 fancy = 0;
70 break;
71 case 'R':
72 timestamp = 2; /* relative timestamp */
73 break;
74 case 'T':
75 timestamp = 1;
76 break;
77 case 't':
78 trpoints = getpoints(optarg);
79 if (trpoints < 0)
80 errx(1, "unknown trace point in %s", optarg);
81 break;
82 default:
83 usage();
84 }
85 argv += optind;
86 argc -= optind;
87
88 if (argc > 1)
89 usage();
90
91 m = (void *)malloc(size = 1025);
92 if (m == NULL)
93 errx(1, "%s", strerror(ENOMEM));
94 if (!freopen(tracefile, "r", stdin))
95 err(1, "%s", tracefile);
96 while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) {
97 if (trpoints & (1<<ktr_header.ktr_type))
98 dumpheader(&ktr_header);
99 if ((ktrlen = ktr_header.ktr_len) < 0)
100 errx(1, "bogus length 0x%x", ktrlen);
101 if (ktrlen > size) {
102 m = (void *)realloc(m, ktrlen+1);
103 if (m == NULL)
104 errx(1, "%s", strerror(ENOMEM));
105 size = ktrlen;
106 }
107 if (ktrlen && fread_tail(m, ktrlen, 1) == 0)
108 errx(1, "data too short");
109 if ((trpoints & (1<<ktr_header.ktr_type)) == 0)
110 continue;
111 switch (ktr_header.ktr_type) {
112 case KTR_SYSCALL:
113 ktrsyscall((struct ktr_syscall *)m);
114 break;
115 case KTR_SYSRET:
116 ktrsysret((struct ktr_sysret *)m);
117 break;
118 case KTR_NAMEI:
119 ktrnamei(m, ktrlen);
120 break;
121 case KTR_GENIO:
122 ktrgenio((struct ktr_genio *)m, ktrlen);
123 break;
124 case KTR_PSIG:
125 ktrpsig((struct ktr_psig *)m);
126 break;
127 case KTR_CSW:
128 ktrcsw((struct ktr_csw *)m);
129 break;
130 }
131 if (tail)
132 (void)fflush(stdout);
133 }
134 }
135
fread_tail(buf,size,num)136 fread_tail(buf, size, num)
137 char *buf;
138 int num, size;
139 {
140 int i;
141
142 while ((i = fread(buf, size, num, stdin)) == 0 && tail) {
143 (void)sleep(1);
144 clearerr(stdin);
145 }
146 return (i);
147 }
148
149 dumpheader(kth)
150 struct ktr_header *kth;
151 {
152 static char unknown[64];
153 static struct timeval prevtime, temp;
154 char *type;
155
156 switch (kth->ktr_type) {
157 case KTR_SYSCALL:
158 type = "CALL";
159 break;
160 case KTR_SYSRET:
161 type = "RET ";
162 break;
163 case KTR_NAMEI:
164 type = "NAMI";
165 break;
166 case KTR_GENIO:
167 type = "GIO ";
168 break;
169 case KTR_PSIG:
170 type = "PSIG";
171 break;
172 case KTR_CSW:
173 type = "CSW";
174 break;
175 default:
176 (void)sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type);
177 type = unknown;
178 }
179
180 (void)printf("%6d %-8s ", kth->ktr_pid, kth->ktr_comm);
181 if (timestamp) {
182 if (timestamp == 2) {
183 temp = kth->ktr_time;
184 timevalsub(&kth->ktr_time, &prevtime);
185 prevtime = temp;
186 }
187 (void)printf("%ld.%06ld ",
188 kth->ktr_time.tv_sec, kth->ktr_time.tv_usec);
189 }
190 (void)printf("%s ", type);
191 }
192
193 #include <sys/syscall.h>
194 #define KTRACE
195 #include "/sys/kern/syscalls.c"
196 #undef KTRACE
197 int nsyscalls = sizeof (syscallnames) / sizeof (syscallnames[0]);
198
199 static char *ptrace_ops[] = {
200 "PT_TRACE_ME", "PT_READ_I", "PT_READ_D", "PT_READ_U",
201 "PT_WRITE_I", "PT_WRITE_D", "PT_WRITE_U", "PT_CONTINUE",
202 "PT_KILL", "PT_STEP",
203 };
204
ktrsyscall(ktr)205 ktrsyscall(ktr)
206 register struct ktr_syscall *ktr;
207 {
208 register argsize = ktr->ktr_argsize;
209 register register_t *ap;
210 char *ioctlname();
211
212 if (ktr->ktr_code >= nsyscalls || ktr->ktr_code < 0)
213 (void)printf("[%d]", ktr->ktr_code);
214 else
215 (void)printf("%s", syscallnames[ktr->ktr_code]);
216 ap = (register_t *)((char *)ktr + sizeof(struct ktr_syscall));
217 if (argsize) {
218 char c = '(';
219 if (fancy) {
220 if (ktr->ktr_code == SYS_ioctl) {
221 char *cp;
222 if (decimal)
223 (void)printf("(%ld", (long)*ap);
224 else
225 (void)printf("(%#lx", (long)*ap);
226 ap++;
227 argsize -= sizeof(register_t);
228 if ((cp = ioctlname(*ap)) != NULL)
229 (void)printf(",%s", cp);
230 else {
231 if (decimal)
232 (void)printf(",%ld",
233 (long)*ap);
234 else
235 (void)printf(",%#lx ",
236 (long)*ap);
237 }
238 c = ',';
239 ap++;
240 argsize -= sizeof(register_t);
241 } else if (ktr->ktr_code == SYS_ptrace) {
242 if (*ap >= 0 && *ap <=
243 sizeof(ptrace_ops) / sizeof(ptrace_ops[0]))
244 (void)printf("(%s", ptrace_ops[*ap]);
245 else
246 (void)printf("(%ld", (long)*ap);
247 c = ',';
248 ap++;
249 argsize -= sizeof(register_t);
250 }
251 }
252 while (argsize) {
253 if (decimal)
254 (void)printf("%c%ld", c, (long)*ap);
255 else
256 (void)printf("%c%#lx", c, (long)*ap);
257 c = ',';
258 ap++;
259 argsize -= sizeof(register_t);
260 }
261 (void)putchar(')');
262 }
263 (void)putchar('\n');
264 }
265
266 ktrsysret(ktr)
267 struct ktr_sysret *ktr;
268 {
269 register int ret = ktr->ktr_retval;
270 register int error = ktr->ktr_error;
271 register int code = ktr->ktr_code;
272
273 if (code >= nsyscalls || code < 0)
274 (void)printf("[%d] ", code);
275 else
276 (void)printf("%s ", syscallnames[code]);
277
278 if (error == 0) {
279 if (fancy) {
280 (void)printf("%d", ret);
281 if (ret < 0 || ret > 9)
282 (void)printf("/%#x", ret);
283 } else {
284 if (decimal)
285 (void)printf("%d", ret);
286 else
287 (void)printf("%#x", ret);
288 }
289 } else if (error == ERESTART)
290 (void)printf("RESTART");
291 else if (error == EJUSTRETURN)
292 (void)printf("JUSTRETURN");
293 else {
294 (void)printf("-1 errno %d", ktr->ktr_error);
295 if (fancy)
296 (void)printf(" %s", strerror(ktr->ktr_error));
297 }
298 (void)putchar('\n');
299 }
300
ktrnamei(cp,len)301 ktrnamei(cp, len)
302 char *cp;
303 {
304 (void)printf("\"%.*s\"\n", len, cp);
305 }
306
307 ktrgenio(ktr, len)
308 struct ktr_genio *ktr;
309 {
310 register int datalen = len - sizeof (struct ktr_genio);
311 register char *dp = (char *)ktr + sizeof (struct ktr_genio);
312 register char *cp;
313 register int col = 0;
314 register width;
315 char visbuf[5];
316 static screenwidth = 0;
317
318 if (screenwidth == 0) {
319 struct winsize ws;
320
321 if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 &&
322 ws.ws_col > 8)
323 screenwidth = ws.ws_col;
324 else
325 screenwidth = 80;
326 }
327 printf("fd %d %s %d bytes\n", ktr->ktr_fd,
328 ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen);
329 if (maxdata && datalen > maxdata)
330 datalen = maxdata;
331 (void)printf(" \"");
332 col = 8;
333 for (; datalen > 0; datalen--, dp++) {
334 (void) vis(visbuf, *dp, VIS_CSTYLE, *(dp+1));
335 cp = visbuf;
336 /*
337 * Keep track of printables and
338 * space chars (like fold(1)).
339 */
340 if (col == 0) {
341 (void)putchar('\t');
342 col = 8;
343 }
344 switch(*cp) {
345 case '\n':
346 col = 0;
347 (void)putchar('\n');
348 continue;
349 case '\t':
350 width = 8 - (col&07);
351 break;
352 default:
353 width = strlen(cp);
354 }
355 if (col + width > (screenwidth-2)) {
356 (void)printf("\\\n\t");
357 col = 8;
358 }
359 col += width;
360 do {
361 (void)putchar(*cp++);
362 } while (*cp);
363 }
364 if (col == 0)
365 (void)printf(" ");
366 (void)printf("\"\n");
367 }
368
369 ktrpsig(psig)
370 struct ktr_psig *psig;
371 {
372 (void)printf("SIG%s ", sys_signame[psig->signo]);
373 if (psig->action == SIG_DFL)
374 (void)printf("SIG_DFL\n");
375 else
376 (void)printf("caught handler=0x%lx mask=0x%x code=0x%x\n",
377 (u_long)psig->action, psig->mask, psig->code);
378 }
379
380 ktrcsw(cs)
381 struct ktr_csw *cs;
382 {
383 (void)printf("%s %s\n", cs->out ? "stop" : "resume",
384 cs->user ? "user" : "kernel");
385 }
386
usage()387 usage()
388 {
389 (void)fprintf(stderr,
390 "usage: kdump [-dnlRT] [-f trfile] [-m maxdata] [-t [cnis]]\n");
391 exit(1);
392 }
393