xref: /dragonfly/usr.bin/ktrdump/ktrdump.c (revision e4adeac1)
1 /*-
2  * Copyright (c) 2002 Jake Burkholder
3  * Copyright (c) 2004 Robert Watson
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  * $FreeBSD: src/usr.bin/ktrdump/ktrdump.c,v 1.10 2005/05/21 09:55:06 ru Exp $
28  */
29 
30 #include <sys/types.h>
31 #include <sys/ktr.h>
32 #include <sys/mman.h>
33 #include <sys/stat.h>
34 #include <sys/queue.h>
35 
36 #include <ctype.h>
37 #include <devinfo.h>
38 #include <err.h>
39 #include <fcntl.h>
40 #include <kvm.h>
41 #include <limits.h>
42 #include <nlist.h>
43 #include <stddef.h>
44 #include <stdint.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <unistd.h>
49 #include <evtr.h>
50 #include <stdarg.h>
51 
52 struct ktr_buffer {
53 	struct ktr_entry *ents;
54 	int modified;
55 	int reset;
56 	int beg_idx;		/* Beginning index */
57 	int end_idx;		/* Ending index */
58 };
59 
60 static struct nlist nl1[] = {
61 	{ .n_name = "_ktr_version" },
62 	{ .n_name = "_ktr_entries" },
63 	{ .n_name = "_ncpus" },
64 	{ .n_name = NULL }
65 };
66 
67 static struct nlist nl2[] = {
68 	{ .n_name = "_tsc_frequency" },
69 	{ .n_name = NULL }
70 };
71 
72 static struct nlist nl_version_ktr_idx[] = {
73 	{ .n_name = "_ktr_idx" },
74 	{ .n_name = "_ktr_buf" },
75 	{ .n_name = NULL }
76 };
77 
78 static struct nlist nl_version_ktr_cpu[] = {
79 	{ .n_name = "_ktr_cpu" },
80 	{ .n_name = NULL }
81 };
82 
83 struct save_ctx {
84 	char save_buf[512];
85 	const void *save_kptr;
86 };
87 
88 typedef void (*ktr_iter_cb_t)(void *, int, int, struct ktr_entry *, uint64_t *);
89 
90 #ifdef __x86_64__
91 /* defined according to the x86_64 ABI spec */
92 struct my_va_list {
93 	uint32_t gp_offset;	/* offset to next available gpr in reg_save_area */
94 	uint32_t fp_offset;	/* offset to next available fpr in reg_save_area */
95 	void *overflow_arg_area;	/* args that are passed on the stack */
96 	struct reg_save_area *reg_save_area;		/* register args */
97 	/*
98 	 * NOT part of the ABI. ->overflow_arg_area gets advanced when code
99 	 * iterates over the arguments with va_arg(). That means we need to
100 	 * keep a copy in order to free the allocated memory (if any)
101 	 */
102 	void *overflow_arg_area_save;
103 } __attribute__((packed));
104 
105 typedef struct my_va_list *machine_va_list;
106 
107 struct reg_save_area {
108 	uint64_t rdi, rsi, rdx, rcx, r8, r9;
109 	/* XMM registers follow, but we don't use them */
110 };
111 #endif
112 
113 static int cflag;
114 static int dflag;
115 static int fflag;
116 static int iflag;
117 static int lflag;
118 static int nflag;
119 static int qflag;
120 static int rflag;
121 static int sflag;
122 static int tflag;
123 static int xflag;
124 static int pflag;
125 static int Mflag;
126 static int Nflag;
127 static double tsc_frequency;
128 static double correction_factor = 0.0;
129 
130 static char corefile[PATH_MAX];
131 static char execfile[PATH_MAX];
132 
133 static char errbuf[_POSIX2_LINE_MAX];
134 static int ncpus;
135 static kvm_t *kd;
136 static int entries_per_buf;
137 static int fifo_mask;
138 static int ktr_version;
139 
140 static void usage(void);
141 static int earliest_ts(struct ktr_buffer *);
142 static void dump_machine_info(evtr_t);
143 static void dump_device_info(evtr_t);
144 static void print_header(FILE *, int);
145 static void print_entry(FILE *, int, int, struct ktr_entry *, u_int64_t *);
146 static void print_callback(void *, int, int, struct ktr_entry *, uint64_t *);
147 static void dump_callback(void *, int, int, struct ktr_entry *, uint64_t *);
148 static struct ktr_info *kvm_ktrinfo(void *, struct save_ctx *);
149 static const char *kvm_string(const char *, struct save_ctx *);
150 static const char *trunc_path(const char *, int);
151 static void read_symbols(const char *);
152 static const char *address_to_symbol(void *, struct save_ctx *);
153 static struct ktr_buffer *ktr_bufs_init(void);
154 static void get_indices(struct ktr_entry **, int *);
155 static void load_bufs(struct ktr_buffer *, struct ktr_entry **, int *);
156 static void iterate_buf(FILE *, struct ktr_buffer *, int, u_int64_t *, ktr_iter_cb_t);
157 static void iterate_bufs_timesorted(FILE *, struct ktr_buffer *, u_int64_t *, ktr_iter_cb_t);
158 static void kvmfprintf(FILE *fp, const char *ctl, va_list va);
159 static int va_list_from_blob(machine_va_list *valist, const char *fmt, char *blob, size_t blobsize);
160 static void va_list_cleanup(machine_va_list *valist);
161 /*
162  * Reads the ktr trace buffer from kernel memory and prints the trace entries.
163  */
164 int
165 main(int ac, char **av)
166 {
167 	struct ktr_buffer *ktr_bufs;
168 	struct ktr_entry **ktr_kbuf;
169 	ktr_iter_cb_t callback = &print_callback;
170 	int *ktr_idx;
171 	FILE *fo;
172 	void *ctx;
173 	int64_t tts;
174 	int *ktr_start_index;
175 	int c;
176 	int n;
177 
178 	/*
179 	 * Parse commandline arguments.
180 	 */
181 	fo = stdout;
182 	while ((c = getopt(ac, av, "acfinqrtxpslA:N:M:o:d")) != -1) {
183 		switch (c) {
184 		case 'a':
185 			cflag = 1;
186 			iflag = 1;
187 			rflag = 1;
188 			xflag = 1;
189 			pflag = 1;
190 			sflag = 1;
191 			break;
192 		case 'c':
193 			cflag = 1;
194 			break;
195 		case 'd':
196 			dflag = 1;
197 			sflag = 1;
198 			callback = &dump_callback;
199 			break;
200 		case 'N':
201 			if (strlcpy(execfile, optarg, sizeof(execfile))
202 			    >= sizeof(execfile))
203 				errx(1, "%s: File name too long", optarg);
204 			Nflag = 1;
205 			break;
206 		case 'f':
207 			fflag = 1;
208 			break;
209 		case 'l':
210 			lflag = 1;
211 			break;
212 		case 'i':
213 			iflag = 1;
214 			break;
215 		case 'A':
216 			correction_factor = strtod(optarg, NULL);
217 			break;
218 		case 'M':
219 			if (strlcpy(corefile, optarg, sizeof(corefile))
220 			    >= sizeof(corefile))
221 				errx(1, "%s: File name too long", optarg);
222 			Mflag = 1;
223 			break;
224 		case 'n':
225 			nflag = 1;
226 			break;
227 		case 'o':
228 			if ((fo = fopen(optarg, "w")) == NULL)
229 				err(1, "%s", optarg);
230 			break;
231 		case 'p':
232 			pflag++;
233 			break;
234 		case 'q':
235 			qflag++;
236 			break;
237 		case 'r':
238 			rflag = 1;
239 			break;
240 		case 's':
241 			sflag = 1;	/* sort across the cpus */
242 			break;
243 		case 't':
244 			tflag = 1;
245 			break;
246 		case 'x':
247 			xflag = 1;
248 			break;
249 		case '?':
250 		default:
251 			usage();
252 		}
253 	}
254 	ctx = fo;
255 	if (dflag) {
256 		ctx = evtr_open_write(fo);
257 		if (!ctx) {
258 			err(1, "Can't create event stream");
259 		}
260 	}
261 	if (cflag + iflag + tflag + xflag + fflag + pflag == 0) {
262 		cflag = 1;
263 		iflag = 1;
264 		tflag = 1;
265 		pflag = 1;
266 	}
267 	if (correction_factor != 0.0 && (rflag == 0 || nflag)) {
268 		fprintf(stderr, "Correction factor can only be applied with -r and without -n\n");
269 		exit(1);
270 	}
271 	ac -= optind;
272 	av += optind;
273 	if (ac != 0)
274 		usage();
275 
276 	/*
277 	 * Open our execfile and corefile, resolve needed symbols and read in
278 	 * the trace buffer.
279 	 */
280 	if ((kd = kvm_openfiles(Nflag ? execfile : NULL,
281 	    Mflag ? corefile : NULL, NULL, O_RDONLY, errbuf)) == NULL)
282 		errx(1, "%s", errbuf);
283 	if (kvm_nlist(kd, nl1) != 0)
284 		errx(1, "%s", kvm_geterr(kd));
285 	if (kvm_read(kd, nl1[0].n_value, &ktr_version, sizeof(ktr_version)) == -1)
286 		errx(1, "%s", kvm_geterr(kd));
287 	if (kvm_read(kd, nl1[2].n_value, &ncpus, sizeof(ncpus)) == -1)
288 		errx(1, "%s", kvm_geterr(kd));
289 	ktr_start_index = malloc(sizeof(*ktr_start_index) * ncpus);
290 	if (ktr_version >= KTR_VERSION_WITH_FREQ && kvm_nlist(kd, nl2) == 0) {
291 		if (kvm_read(kd, nl2[0].n_value, &tts, sizeof(tts)) == -1)
292 			errx(1, "%s", kvm_geterr(kd));
293 		tsc_frequency = (double)tts;
294 	}
295 	if (ktr_version > KTR_VERSION)
296 		errx(1, "ktr version too high for us to handle");
297 	if (kvm_read(kd, nl1[1].n_value, &entries_per_buf,
298 				sizeof(entries_per_buf)) == -1)
299 		errx(1, "%s", kvm_geterr(kd));
300 	fifo_mask = entries_per_buf - 1;
301 
302 	printf("TSC frequency is %6.3f MHz\n", tsc_frequency / 1000000.0);
303 
304 	if (dflag) {
305 		dump_machine_info((evtr_t)ctx);
306 		dump_device_info((evtr_t)ctx);
307 	}
308 	ktr_kbuf = calloc(ncpus, sizeof(*ktr_kbuf));
309 	ktr_idx = calloc(ncpus, sizeof(*ktr_idx));
310 
311 	if (nflag == 0)
312 		read_symbols(Nflag ? execfile : NULL);
313 
314 	if (ktr_version < KTR_VERSION_KTR_CPU) {
315 		if (kvm_nlist(kd, nl_version_ktr_idx))
316 			errx(1, "%s", kvm_geterr(kd));
317 	} else {
318 		if (kvm_nlist(kd, nl_version_ktr_cpu))
319 			errx(1, "%s", kvm_geterr(kd));
320 	}
321 
322 	get_indices(ktr_kbuf, ktr_idx);
323 
324 	ktr_bufs = ktr_bufs_init();
325 
326 	if (sflag) {
327 		u_int64_t last_timestamp = 0;
328 		do {
329 			load_bufs(ktr_bufs, ktr_kbuf, ktr_idx);
330 			iterate_bufs_timesorted(ctx, ktr_bufs, &last_timestamp,
331 						callback);
332 			if (lflag)
333 				usleep(1000000 / 10);
334 		} while (lflag);
335 	} else {
336 		u_int64_t *last_timestamp = calloc(sizeof(u_int64_t), ncpus);
337 		do {
338 			load_bufs(ktr_bufs, ktr_kbuf, ktr_idx);
339 			for (n = 0; n < ncpus; ++n)
340 				iterate_buf(ctx, ktr_bufs, n, &last_timestamp[n],
341 					callback);
342 			if (lflag)
343 				usleep(1000000 / 10);
344 		} while (lflag);
345 	}
346 	if (dflag)
347 		evtr_close(ctx);
348 	return (0);
349 }
350 
351 static
352 int
353 dump_devinfo(struct devinfo_dev *dev, void *arg)
354 {
355 	struct evtr_event ev;
356 	evtr_t evtr = (evtr_t)arg;
357 	const char *fmt = "#devicenames[\"%s\"] = %#lx";
358 	char fmtdatabuf[sizeof(char *) + sizeof(devinfo_handle_t)];
359 	char *fmtdata = fmtdatabuf;
360 
361 	if (!dev->dd_name[0])
362 		return 0;
363 	ev.type = EVTR_TYPE_PROBE;
364 	ev.ts = 0;
365 	ev.line = 0;
366 	ev.file = NULL;
367 	ev.cpu = -1;
368 	ev.func = NULL;
369 	ev.fmt = fmt;
370 	((char **)fmtdata)[0] = &dev->dd_name[0];
371 	fmtdata += sizeof(char *);
372 	((devinfo_handle_t *)fmtdata)[0] = dev->dd_handle;
373 	ev.fmtdata = fmtdatabuf;
374 	ev.fmtdatalen = sizeof(fmtdatabuf);
375 
376 	if (evtr_dump_event(evtr, &ev)) {
377 		err(1, "%s", evtr_errmsg(evtr));
378 	}
379 
380 	return devinfo_foreach_device_child(dev, dump_devinfo, evtr);
381 }
382 
383 static
384 void
385 dump_device_info(evtr_t evtr)
386 {
387 	struct devinfo_dev *root;
388 	if (devinfo_init())
389 		return;
390 	if (!(root = devinfo_handle_to_device(DEVINFO_ROOT_DEVICE))) {
391 		warn("can't find root device");
392 		return;
393 	}
394 	devinfo_foreach_device_child(root, dump_devinfo, evtr);
395 }
396 
397 static
398 void
399 dump_machine_info(evtr_t evtr)
400 {
401 	struct evtr_event ev;
402 	int i;
403 
404 	bzero(&ev, sizeof(ev));
405 	ev.type = EVTR_TYPE_SYSINFO;
406 	ev.ncpus = ncpus;
407 	evtr_dump_event(evtr, &ev);
408 	if (evtr_error(evtr)) {
409 		err(1, "%s", evtr_errmsg(evtr));
410 	}
411 
412 	for (i = 0; i < ncpus; ++i) {
413 		bzero(&ev, sizeof(ev));
414 		ev.type = EVTR_TYPE_CPUINFO;
415 		ev.cpu = i;
416 		ev.cpuinfo.freq = tsc_frequency;
417 		evtr_dump_event(evtr, &ev);
418 		if (evtr_error(evtr)) {
419 			err(1, "%s", evtr_errmsg(evtr));
420 		}
421 	}
422 }
423 
424 static void
425 print_header(FILE *fo, int row)
426 {
427 	if (qflag == 0 && (u_int32_t)row % 20 == 0) {
428 		fprintf(fo, "%-6s ", "index");
429 		if (cflag)
430 			fprintf(fo, "%-3s ", "cpu");
431 		if (tflag || rflag)
432 			fprintf(fo, "%-16s ", "timestamp");
433 		if (xflag) {
434 			if (nflag)
435 			    fprintf(fo, "%-18s %-18s ", "caller2", "caller1");
436 			else
437 			    fprintf(fo, "%-25s %-25s ", "caller2", "caller1");
438 		}
439 		if (iflag)
440 			fprintf(fo, "%-20s ", "ID");
441 		if (fflag)
442 			fprintf(fo, "%10s%-30s", "", "file and line");
443 		if (pflag)
444 			fprintf(fo, "%s", "trace");
445 		fprintf(fo, "\n");
446 	}
447 }
448 
449 static void
450 print_entry(FILE *fo, int n, int row, struct ktr_entry *entry,
451 	    u_int64_t *last_timestamp)
452 {
453 	struct ktr_info *info = NULL;
454 	static struct save_ctx nctx, pctx, fmtctx, symctx, infoctx;
455 
456 	fprintf(fo, "%06x ", row & 0x00FFFFFF);
457 	if (cflag)
458 		fprintf(fo, "%-3d ", n);
459 	if (tflag || rflag) {
460 		if (rflag && !nflag && tsc_frequency != 0.0) {
461 			fprintf(fo, "%13.3f uS ",
462 				(double)(entry->ktr_timestamp - *last_timestamp) * 1000000.0 / tsc_frequency - correction_factor);
463 		} else if (rflag) {
464 			fprintf(fo, "%-16ju ",
465 			    (uintmax_t)(entry->ktr_timestamp - *last_timestamp));
466 		} else {
467 			fprintf(fo, "%-16ju ",
468 			    (uintmax_t)entry->ktr_timestamp);
469 		}
470 	}
471 	if (xflag) {
472 		if (nflag) {
473 		    fprintf(fo, "%p %p ",
474 			    entry->ktr_caller2, entry->ktr_caller1);
475 		} else {
476 		    fprintf(fo, "%-25s ",
477 			    address_to_symbol(entry->ktr_caller2, &symctx));
478 		    fprintf(fo, "%-25s ",
479 			    address_to_symbol(entry->ktr_caller1, &symctx));
480 		}
481 	}
482 	if (iflag) {
483 		info = kvm_ktrinfo(entry->ktr_info, &infoctx);
484 		if (info)
485 			fprintf(fo, "%-20s ", kvm_string(info->kf_name, &nctx));
486 		else
487 			fprintf(fo, "%-20s ", "<empty>");
488 	}
489 	if (fflag)
490 		fprintf(fo, "%34s:%-4d ",
491 			trunc_path(kvm_string(entry->ktr_file, &pctx), 34),
492 			entry->ktr_line);
493 	if (pflag) {
494 		if (info == NULL)
495 			info = kvm_ktrinfo(entry->ktr_info, &infoctx);
496 		if (info) {
497 			machine_va_list ap;
498 			const char *fmt;
499 			fmt = kvm_string(info->kf_format, &fmtctx);
500 			if (va_list_from_blob(&ap, fmt,
501 					      (char *)&entry->ktr_data,
502 					      info->kf_data_size))
503 				err(2, "Can't generate va_list from %s", fmt);
504 			kvmfprintf(fo, kvm_string(info->kf_format, &fmtctx),
505 				   (void *)ap);
506 			va_list_cleanup(&ap);
507 		}
508 	}
509 	fprintf(fo, "\n");
510 	*last_timestamp = entry->ktr_timestamp;
511 }
512 
513 static
514 void
515 print_callback(void *ctx, int n, int row, struct ktr_entry *entry, uint64_t *last_ts)
516 {
517 	FILE *fo = (FILE *)ctx;
518 	print_header(fo, row);
519 	print_entry(fo, n, row, entry, last_ts);
520 }
521 
522 /*
523  * If free == 0, replace all (kvm) string pointers in fmtdata with pointers
524  * to user-allocated copies of the strings.
525  * If free != 0, free those pointers.
526  */
527 static
528 int
529 mangle_string_ptrs(const char *fmt, uint8_t *fmtdata, int dofree)
530 {
531 	const char *f, *p;
532 	size_t skipsize, intsz;
533 	static struct save_ctx strctx;
534 	int ret = 0;
535 
536 	for (f = fmt; f[0] != '\0'; ++f) {
537 		if (f[0] != '%')
538 			continue;
539 		++f;
540 		skipsize = 0;
541 		for (p = f; p[0]; ++p) {
542 			int again = 0;
543 			/*
544 			 * Eat flags. Notice this will accept duplicate
545 			 * flags.
546 			 */
547 			switch (p[0]) {
548 			case '#':
549 			case '0':
550 			case '-':
551 			case ' ':
552 			case '+':
553 			case '\'':
554 				again = !0;
555 				break;
556 			}
557 			if (!again)
558 				break;
559 		}
560 		/* Eat minimum field width, if any */
561 		for (; isdigit(p[0]); ++p)
562 			;
563 		if (p[0] == '.')
564 			++p;
565 		/* Eat precision, if any */
566 		for (; isdigit(p[0]); ++p)
567 			;
568 		intsz = 0;
569 		switch (p[0]) {
570 		case 'h':
571 			if (p[1] == 'h') {
572 				++p;
573 				intsz = sizeof(char);
574 			} else {
575 				intsz = sizeof(short);
576 			}
577 			break;
578 		case 'l':
579 			if (p[1] == 'l') {
580 				++p;
581 				intsz = sizeof(long long);
582 			} else {
583 				intsz = sizeof(long);
584 			}
585 			break;
586 		case 'j':
587 			intsz = sizeof(intmax_t);
588 			break;
589 		case 't':
590 			intsz = sizeof(ptrdiff_t);
591 			break;
592 		case 'z':
593 			intsz = sizeof(size_t);
594 			break;
595 		default:
596 			break;
597 		}
598 		if (intsz != 0)
599 			++p;
600 		else
601 			intsz = sizeof(int);
602 
603 		switch (p[0]) {
604 		case 'd':
605 		case 'i':
606 		case 'o':
607 		case 'u':
608 		case 'x':
609 		case 'X':
610 		case 'c':
611 			skipsize = intsz;
612 			break;
613 		case 'p':
614 			skipsize = sizeof(void *);
615 			break;
616 		case 'f':
617 			if (p[-1] == 'l')
618 				skipsize = sizeof(double);
619 			else
620 				skipsize = sizeof(float);
621 			break;
622 		case 's':
623 			if (dofree) {
624 			  char *t = ((char **)fmtdata)[0];
625 			  free(t);
626 			  skipsize = sizeof(char *);
627 			} else {
628 			  char *t = strdup(kvm_string(((char **)fmtdata)[0],
629 							  &strctx));
630 			  ((const char **)fmtdata)[0] = t;
631 
632 				skipsize = sizeof(char *);
633 			}
634 			++ret;
635 			break;
636 		default:
637 			fprintf(stderr, "Unknown conversion specifier %c "
638 				"in fmt starting with %s\n", p[0], f - 1);
639 			return -1;
640 		}
641 		fmtdata += skipsize;
642 	}
643 	return ret;
644 }
645 
646 static
647 void
648 dump_callback(void *ctx, int n, int row __unused, struct ktr_entry *entry,
649 	      uint64_t *last_ts __unused)
650 {
651 	evtr_t evtr = (evtr_t)ctx;
652 	struct evtr_event ev;
653 	static struct save_ctx pctx, fmtctx, infoctx;
654 	struct ktr_info *ki;
655 	int conv = 0;	/* pointless */
656 
657 	ev.ts = entry->ktr_timestamp;
658 	ev.type = EVTR_TYPE_PROBE;
659 	ev.line = entry->ktr_line;
660 	ev.file = kvm_string(entry->ktr_file, &pctx);
661 	ev.func = NULL;
662 	ev.cpu = n;
663 	if ((ki = kvm_ktrinfo(entry->ktr_info, &infoctx))) {
664 		ev.fmt = kvm_string(ki->kf_format, &fmtctx);
665 		ev.fmtdata = entry->ktr_data;
666 		if ((conv = mangle_string_ptrs(ev.fmt,
667 					       __DECONST(uint8_t *, ev.fmtdata),
668 					       0)) < 0)
669 			errx(1, "Can't parse format string");
670 		ev.fmtdatalen = ki->kf_data_size;
671 	} else {
672 		ev.fmt = ev.fmtdata = NULL;
673 		ev.fmtdatalen = 0;
674 	}
675 	if (evtr_dump_event(evtr, &ev)) {
676 		err(1, "%s", evtr_errmsg(evtr));
677 	}
678 	if (ev.fmtdata && conv) {
679 		mangle_string_ptrs(ev.fmt, __DECONST(uint8_t *, ev.fmtdata),
680 				   !0);
681 	}
682 }
683 
684 static
685 struct ktr_info *
686 kvm_ktrinfo(void *kptr, struct save_ctx *ctx)
687 {
688 	struct ktr_info *ki = (void *)ctx->save_buf;
689 
690 	if (kptr == NULL)
691 		return(NULL);
692 	if (ctx->save_kptr != kptr) {
693 		if (kvm_read(kd, (uintptr_t)kptr, ki, sizeof(*ki)) == -1) {
694 			bzero(ki, sizeof(*ki));
695 		} else {
696 			ctx->save_kptr = kptr;
697 		}
698 	}
699 	return(ki);
700 }
701 
702 static
703 const char *
704 kvm_string(const char *kptr, struct save_ctx *ctx)
705 {
706 	u_int l;
707 	u_int n;
708 
709 	if (kptr == NULL)
710 		return("?");
711 	if (ctx->save_kptr != (const void *)kptr) {
712 		ctx->save_kptr = (const void *)kptr;
713 		l = 0;
714 		while (l < sizeof(ctx->save_buf) - 1) {
715 			n = 256 - ((intptr_t)(kptr + l) & 255);
716 			if (n > sizeof(ctx->save_buf) - l - 1)
717 				n = sizeof(ctx->save_buf) - l - 1;
718 			if (kvm_read(kd, (uintptr_t)(kptr + l), ctx->save_buf + l, n) < 0)
719 				break;
720 			while (l < sizeof(ctx->save_buf) && n) {
721 			    if (ctx->save_buf[l] == 0)
722 				    break;
723 			    --n;
724 			    ++l;
725 			}
726 			if (n)
727 			    break;
728 		}
729 		ctx->save_buf[l] = 0;
730 	}
731 	return(ctx->save_buf);
732 }
733 
734 static
735 const char *
736 trunc_path(const char *str, int maxlen)
737 {
738 	int len = strlen(str);
739 
740 	if (len > maxlen)
741 		return(str + len - maxlen);
742 	else
743 		return(str);
744 }
745 
746 struct symdata {
747 	TAILQ_ENTRY(symdata) link;
748 	const char *symname;
749 	char *symaddr;
750 	char symtype;
751 };
752 
753 static TAILQ_HEAD(symlist, symdata) symlist;
754 static struct symdata *symcache;
755 static char *symbegin;
756 static char *symend;
757 
758 static
759 void
760 read_symbols(const char *file)
761 {
762 	char buf[256];
763 	char cmd[256];
764 	size_t buflen = sizeof(buf);
765 	FILE *fp;
766 	struct symdata *sym = NULL;
767 	char *s1;
768 	char *s2;
769 	char *s3;
770 
771 	TAILQ_INIT(&symlist);
772 
773 	if (file == NULL) {
774 		if (sysctlbyname("kern.bootfile", buf, &buflen, NULL, 0) < 0)
775 			file = "/boot/kernel/kernel";
776 		else
777 			file = buf;
778 	}
779 	snprintf(cmd, sizeof(cmd), "nm -n %s", file);
780 	if ((fp = popen(cmd, "r")) != NULL) {
781 		while (fgets(buf, sizeof(buf), fp) != NULL) {
782 		    s1 = strtok(buf, " \t\n");
783 		    s2 = strtok(NULL, " \t\n");
784 		    s3 = strtok(NULL, " \t\n");
785 		    if (s1 && s2 && s3) {
786 			sym = malloc(sizeof(struct symdata));
787 			sym->symaddr = (char *)strtoul(s1, NULL, 16);
788 			sym->symtype = s2[0];
789 			sym->symname = strdup(s3);
790 			if (strcmp(s3, "kernbase") == 0)
791 				symbegin = sym->symaddr;
792 			if (strcmp(s3, "end") == 0 || strcmp(s3, "_end") == 0)
793 				symend = sym->symaddr;
794 			TAILQ_INSERT_TAIL(&symlist, sym, link);
795 		    }
796 		}
797 		pclose(fp);
798 	}
799 	if (symend == NULL) {
800 		if (sym != NULL)
801 			symend = sym->symaddr;
802 		else
803 			symend = (char *)-1;
804 	}
805 	symcache = TAILQ_FIRST(&symlist);
806 }
807 
808 static
809 const char *
810 address_to_symbol(void *kptr, struct save_ctx *ctx)
811 {
812 	char *buf = ctx->save_buf;
813 	int size = sizeof(ctx->save_buf);
814 
815 	if (symcache == NULL ||
816 	   (char *)kptr < symbegin || (char *)kptr >= symend
817 	) {
818 		snprintf(buf, size, "%p", kptr);
819 		return(buf);
820 	}
821 	while ((char *)symcache->symaddr < (char *)kptr) {
822 		if (TAILQ_NEXT(symcache, link) == NULL)
823 			break;
824 		symcache = TAILQ_NEXT(symcache, link);
825 	}
826 	while ((char *)symcache->symaddr > (char *)kptr) {
827 		if (symcache != TAILQ_FIRST(&symlist))
828 			symcache = TAILQ_PREV(symcache, symlist, link);
829 	}
830 	snprintf(buf, size, "%s+%d", symcache->symname,
831 		(int)((char *)kptr - symcache->symaddr));
832 	return(buf);
833 }
834 
835 static
836 struct ktr_buffer *
837 ktr_bufs_init(void)
838 {
839 	struct ktr_buffer *ktr_bufs, *it;
840 	int i;
841 
842 	ktr_bufs = malloc(sizeof(*ktr_bufs) * ncpus);
843 	if (!ktr_bufs)
844 		err(1, "can't allocate data structures");
845 	for (i = 0; i < ncpus; ++i) {
846 		it = ktr_bufs + i;
847 		it->ents = malloc(sizeof(struct ktr_entry) * entries_per_buf);
848 		if (it->ents == NULL)
849 			err(1, "can't allocate data structures");
850 		it->reset = 1;
851 		it->beg_idx = -1;
852 		it->end_idx = -1;
853 	}
854 	return ktr_bufs;
855 }
856 
857 static
858 void
859 get_indices(struct ktr_entry **ktr_kbuf, int *ktr_idx)
860 {
861 	static struct ktr_cpu *ktr_cpus;
862 	int i;
863 
864 	if (ktr_cpus == NULL)
865 		ktr_cpus = malloc(sizeof(*ktr_cpus) * ncpus);
866 
867 	if (ktr_version < KTR_VERSION_KTR_CPU) {
868 		if (kvm_read(kd, nl_version_ktr_idx[0].n_value, ktr_idx,
869 		    sizeof(*ktr_idx) * ncpus) == -1) {
870 			errx(1, "%s", kvm_geterr(kd));
871 		}
872 		if (ktr_kbuf[0] == NULL) {
873 			if (kvm_read(kd, nl_version_ktr_idx[1].n_value,
874 			    ktr_kbuf, sizeof(*ktr_kbuf) * ncpus) == -1) {
875 				errx(1, "%s", kvm_geterr(kd));
876 			}
877 		}
878 	} else {
879 		if (kvm_read(kd, nl_version_ktr_cpu[0].n_value,
880 			     ktr_cpus, sizeof(*ktr_cpus) * ncpus) == -1) {
881 				errx(1, "%s", kvm_geterr(kd));
882 		}
883 		for (i = 0; i < ncpus; ++i) {
884 			ktr_idx[i] = ktr_cpus[i].core.ktr_idx;
885 			ktr_kbuf[i] = ktr_cpus[i].core.ktr_buf;
886 		}
887 	}
888 }
889 
890 /*
891  * Get the trace buffer data from the kernel
892  */
893 static
894 void
895 load_bufs(struct ktr_buffer *ktr_bufs, struct ktr_entry **kbufs, int *ktr_idx)
896 {
897 	struct ktr_buffer *kbuf;
898 	int i;
899 
900 	get_indices(kbufs, ktr_idx);
901 	for (i = 0; i < ncpus; ++i) {
902 		kbuf = &ktr_bufs[i];
903 		if (ktr_idx[i] == kbuf->end_idx)
904 			continue;
905 		kbuf->end_idx = ktr_idx[i];
906 
907 		/*
908 		 * If we do not have a notion of the beginning index, assume
909 		 * it is entries_per_buf before the ending index.  Don't
910 		 * worry about underflows/negative numbers, the indices will
911 		 * be masked.
912 		 */
913 		if (kbuf->reset) {
914 			kbuf->beg_idx = kbuf->end_idx - entries_per_buf + 1;
915 			kbuf->reset = 0;
916 		}
917 		if (kvm_read(kd, (uintptr_t)kbufs[i], ktr_bufs[i].ents,
918 				sizeof(struct ktr_entry) * entries_per_buf)
919 									== -1)
920 			errx(1, "%s", kvm_geterr(kd));
921 		kbuf->modified = 1;
922 		kbuf->beg_idx = earliest_ts(kbuf);
923 	}
924 
925 }
926 
927 /*
928  * Locate the earliest timestamp iterating backwards from end_idx, but
929  * not going further back then beg_idx.  We have to do this because
930  * the kernel uses a circulating buffer.
931  */
932 static
933 int
934 earliest_ts(struct ktr_buffer *buf)
935 {
936 	struct ktr_entry *save;
937 	int count, scan, i, earliest;
938 
939 	count = 0;
940 	earliest = buf->end_idx - 1;
941 	save = &buf->ents[earliest & fifo_mask];
942 	for (scan = buf->end_idx - 1; scan != buf->beg_idx -1; --scan) {
943 		i = scan & fifo_mask;
944 		if (buf->ents[i].ktr_timestamp <= save->ktr_timestamp &&
945 		    buf->ents[i].ktr_timestamp > 0)
946 			earliest = scan;
947 		/*
948 		 * We may have gotten so far behind that beg_idx wrapped
949 		 * more then once around the buffer.  Just stop
950 		 */
951 		if (++count == entries_per_buf)
952 			break;
953 	}
954 	return earliest;
955 }
956 
957 static
958 void
959 iterate_buf(FILE *fo, struct ktr_buffer *ktr_bufs, int cpu,
960 	    u_int64_t *last_timestamp, ktr_iter_cb_t cb)
961 {
962 	struct ktr_buffer *buf = ktr_bufs + cpu;
963 
964 	if (buf->modified == 0)
965 		return;
966 	if (*last_timestamp == 0) {
967 		*last_timestamp =
968 			buf->ents[buf->beg_idx & fifo_mask].ktr_timestamp;
969 	}
970 	while (buf->beg_idx != buf->end_idx) {
971 		cb(fo, cpu, buf->beg_idx,
972 		   &buf->ents[buf->beg_idx & fifo_mask],
973 		   last_timestamp);
974 		++buf->beg_idx;
975 	}
976 	buf->modified = 0;
977 }
978 
979 static
980 void
981 iterate_bufs_timesorted(FILE *fo, struct ktr_buffer *ktr_bufs,
982 			u_int64_t *last_timestamp, ktr_iter_cb_t cb)
983 {
984 	struct ktr_entry *ent;
985 	struct ktr_buffer *buf;
986 	int n, bestn;
987 	u_int64_t ts;
988 	static int row = 0;
989 
990 	for (;;) {
991 		ts = 0;
992 		bestn = -1;
993 		for (n = 0; n < ncpus; ++n) {
994 			buf = ktr_bufs + n;
995 			if (buf->beg_idx == buf->end_idx)
996 				continue;
997 			ent = &buf->ents[buf->beg_idx & fifo_mask];
998 			if (ts == 0 || (ts >= ent->ktr_timestamp)) {
999 				ts = ent->ktr_timestamp;
1000 				bestn = n;
1001 			}
1002 		}
1003 		if ((bestn < 0) || (ts < *last_timestamp))
1004 			break;
1005 		buf = ktr_bufs + bestn;
1006 		cb(fo, bestn, row,
1007 		   &buf->ents[buf->beg_idx & fifo_mask],
1008 		   last_timestamp);
1009 		++buf->beg_idx;
1010 		*last_timestamp = ts;
1011 		++row;
1012 	}
1013 }
1014 
1015 static
1016 void
1017 kvmfprintf(FILE *fp, const char *ctl, va_list va)
1018 {
1019 	int n;
1020 	int is_long;
1021 	int is_done;
1022 	char fmt[256];
1023 	static struct save_ctx strctx;
1024 	const char *s;
1025 
1026 	while (*ctl) {
1027 		for (n = 0; ctl[n]; ++n) {
1028 			fmt[n] = ctl[n];
1029 			if (ctl[n] == '%')
1030 				break;
1031 		}
1032 		if (n == 0) {
1033 			is_long = 0;
1034 			is_done = 0;
1035 			n = 1;
1036 			while (n < (int)sizeof(fmt)) {
1037 				fmt[n] = ctl[n];
1038 				fmt[n+1] = 0;
1039 
1040 				switch(ctl[n]) {
1041 				case 'p':
1042 					is_long = 1;
1043 					/* fall through */
1044 				case 'd':
1045 				case 'i':
1046 				case 'u':
1047 				case 'x':
1048 				case 'o':
1049 				case 'X':
1050 					/*
1051 					 * Integral
1052 					 */
1053 					switch(is_long) {
1054 					case 0:
1055 						fprintf(fp, fmt,
1056 							va_arg(va, int));
1057 						break;
1058 					case 1:
1059 						fprintf(fp, fmt,
1060 							va_arg(va, long));
1061 						break;
1062 					case 2:
1063 						fprintf(fp, fmt,
1064 						    va_arg(va, long long));
1065 						break;
1066 					case 3:
1067 						fprintf(fp, fmt,
1068 						    va_arg(va, size_t));
1069 						break;
1070 					}
1071 					++n;
1072 					is_done = 1;
1073 					break;
1074 				case 'c':
1075 				        fprintf(fp, "%c", va_arg(va, int));
1076 					++n;
1077 					is_done = 1;
1078 					break;
1079 				case 's':
1080 					/*
1081 					 * String
1082 					 */
1083 					s = kvm_string(va_arg(va, char *), &strctx);
1084 					fwrite(s, 1, strlen(s), fp);
1085 					++n;
1086 					is_done = 1;
1087 					break;
1088 				case 'f':
1089 					/*
1090 					 * Floating
1091 					 */
1092 					fprintf(fp, fmt,
1093 						va_arg(va, double));
1094 					++n;
1095 					break;
1096 				case 'j':
1097 				case 't':
1098 					is_long = 2;
1099 					break;
1100 				case 'z':
1101 					is_long = 3;
1102 					break;
1103 				case 'h':
1104 					is_long = 0;
1105 					break;
1106 				case 'l':
1107 					if (is_long)
1108 						is_long = 2;
1109 					else
1110 						is_long = 1;
1111 					break;
1112 				case '#':
1113 				case '.':
1114 				case '-':
1115 				case '+':
1116 				case '0':
1117 				case '1':
1118 				case '2':
1119 				case '3':
1120 				case '4':
1121 				case '5':
1122 				case '6':
1123 				case '7':
1124 				case '8':
1125 				case '9':
1126 					break;
1127 				default:
1128 					is_done = 1;
1129 					break;
1130 				}
1131 				if (is_done)
1132 					break;
1133 				++n;
1134 			}
1135 		} else {
1136 			fmt[n] = 0;
1137 			fprintf(fp, fmt, NULL);
1138 		}
1139 		ctl += n;
1140 	}
1141 }
1142 
1143 static void
1144 usage(void)
1145 {
1146 	fprintf(stderr, "usage: ktrdump [-acfilnpqrstx] [-A factor] "
1147 			"[-N execfile] [-M corefile] [-o outfile]\n");
1148 	exit(1);
1149 }
1150 
1151 enum argument_class {
1152 	ARGCLASS_NONE,
1153 	ARGCLASS_INTEGER,
1154 	ARGCLASS_FP,
1155 	ARGCLASS_MEMORY,
1156 	ARGCLASS_ERR,
1157 };
1158 static size_t
1159 conversion_size(const char *fmt, enum argument_class *argclass)
1160 {
1161 	const char *p;
1162 	size_t convsize, intsz;
1163 
1164 	*argclass = ARGCLASS_ERR;
1165 	if (fmt[0] != '%')
1166 		return -1;
1167 
1168 	convsize = -1;
1169 	for (p = fmt + 1; p[0]; ++p) {
1170 		int again = 0;
1171 		/*
1172 		 * Eat flags. Notice this will accept duplicate
1173 		 * flags.
1174 		 */
1175 		switch (p[0]) {
1176 		case '#':
1177 		case '0':
1178 		case '-':
1179 		case ' ':
1180 		case '+':
1181 		case '\'':
1182 			again = !0;
1183 			break;
1184 		}
1185 		if (!again)
1186 			break;
1187 	}
1188 	/* Eat minimum field width, if any */
1189 	for (; isdigit(p[0]); ++p)
1190 			;
1191 	if (p[0] == '.')
1192 		++p;
1193 	/* Eat precision, if any */
1194 	for (; isdigit(p[0]); ++p)
1195 		;
1196 	intsz = 0;
1197 	switch (p[0]) {
1198 	case 'h':
1199 		if (p[1] == 'h') {
1200 			++p;
1201 			intsz = sizeof(char);
1202 		} else {
1203 			intsz = sizeof(short);
1204 		}
1205 		break;
1206 	case 'l':
1207 		if (p[1] == 'l') {
1208 			++p;
1209 			intsz = sizeof(long long);
1210 		} else {
1211 			intsz = sizeof(long);
1212 		}
1213 		break;
1214 	case 'j':
1215 		intsz = sizeof(intmax_t);
1216 		break;
1217 	case 't':
1218 		intsz = sizeof(ptrdiff_t);
1219 		break;
1220 	case 'z':
1221 		intsz = sizeof(size_t);
1222 		break;
1223 	default:
1224 		p--;	/* Anticipate the ++p that follows. Yes, I know. Eeek. */
1225 		break;
1226 	}
1227 	if (intsz == 0)
1228 		intsz = sizeof(int);
1229 	++p;
1230 
1231 	switch (p[0]) {
1232 	case 'c':
1233 		/* for %c, we only store 1 byte in the ktr entry */
1234 		convsize = sizeof(char);
1235 		*argclass = ARGCLASS_INTEGER;
1236 		break;
1237 	case 'd':
1238 	case 'i':
1239 	case 'o':
1240 	case 'u':
1241 	case 'x':
1242 	case 'X':
1243 		convsize = intsz;
1244 		*argclass = ARGCLASS_INTEGER;
1245 		break;
1246 	case 'p':
1247 		convsize = sizeof(void *);
1248 		*argclass = ARGCLASS_INTEGER;
1249 		break;
1250 	case 'f':
1251 		if (p[-1] == 'l')
1252 			convsize = sizeof(double);
1253 		else
1254 			convsize = sizeof(float);
1255 		*argclass = ARGCLASS_FP;
1256 		break;
1257 	case 's':
1258 		convsize = sizeof(char *);
1259 		*argclass = ARGCLASS_INTEGER;
1260 		break;
1261 	case '%':
1262 		convsize = 0;
1263 		*argclass = ARGCLASS_NONE;
1264 		break;
1265 	default:
1266 		fprintf(stderr, "Unknown conversion specifier %c "
1267 			"in fmt starting with %s\n", p[0], fmt - 1);
1268 		return -2;
1269 	}
1270 	return convsize;
1271 }
1272 
1273 #ifdef __x86_64__
1274 static int
1275 va_list_push_integral(struct my_va_list *valist, void *val, size_t valsize,
1276 		     size_t *stacksize)
1277 {
1278 	uint64_t r;
1279 
1280 	switch (valsize) {
1281 	case 1:
1282 		r = *(uint8_t *)val; break;
1283 	case 2:
1284 		r = *(uint32_t *)val; break;
1285 	case 4:
1286 		r = (*(uint32_t *)val); break;
1287 	case 8:
1288 		r = *(uint64_t *)val; break;
1289 	default:
1290 		err(1, "WTF");
1291 	}
1292 	/* we always need to push the full 8 bytes */
1293 	if ((valist->gp_offset + valsize) <= 48) {	/* got a free reg */
1294 
1295 		memcpy(((char *)valist->reg_save_area + valist->gp_offset),
1296 		       &r, sizeof(r));
1297 		valist->gp_offset += sizeof(r);
1298 		return 0;
1299 	}
1300 	/* push to "stack" */
1301 	if (!(valist->overflow_arg_area = realloc(valist->overflow_arg_area,
1302 						  *stacksize + sizeof(r))))
1303 		return -1;
1304 	/*
1305 	 * Keep a pointer to the start of the allocated memory block so
1306 	 * we can free it later. We need to update it after every realloc().
1307 	 */
1308 	valist->overflow_arg_area_save = valist->overflow_arg_area;
1309 	memcpy((char *)valist->overflow_arg_area + *stacksize, &r, sizeof(r));
1310 	*stacksize += sizeof(r);
1311 	return 0;
1312 }
1313 
1314 static void
1315 va_list_rewind(struct my_va_list *valist)
1316 {
1317 	valist->gp_offset = 0;
1318 }
1319 
1320 static void
1321 va_list_cleanup(machine_va_list *_valist)
1322 {
1323 	machine_va_list valist;
1324 	if (!_valist || !*_valist)
1325 		return;
1326 	valist = *_valist;
1327 	if (valist->reg_save_area)
1328 		free(valist->reg_save_area);
1329 	if (valist->overflow_arg_area_save)
1330 		free(valist->overflow_arg_area_save);
1331 	free(valist);
1332 }
1333 
1334 static int
1335 va_list_from_blob(machine_va_list *_valist, const char *fmt, char *blob, size_t blobsize)
1336 {
1337 	machine_va_list valist;
1338 	struct reg_save_area *regs;
1339 	enum argument_class argclass;
1340 	const char *f;
1341 	size_t stacksize, sz;
1342 
1343 	if (!(valist = malloc(sizeof(*valist))))
1344 		return -1;
1345 	if (!(regs = malloc(sizeof(*regs))))
1346 		goto free_valist;
1347 	*valist = (struct my_va_list) {
1348 		.gp_offset = 0,
1349 		.fp_offset = 0,
1350 		.overflow_arg_area = NULL,
1351 		.reg_save_area = regs,
1352 		.overflow_arg_area_save = NULL,
1353 	};
1354 	stacksize = 0;
1355 
1356 	for (f = fmt; *f != '\0'; ++f) {
1357 		if (*f != '%')
1358 			continue;
1359 		sz = conversion_size(f, &argclass);
1360 		if (argclass == ARGCLASS_INTEGER) {
1361 			if (blobsize < sz) {
1362 				fprintf(stderr, "not enough data available "
1363 					"for format: %s\n", fmt);
1364 				goto free_areas;
1365 			}
1366 			if (va_list_push_integral(valist, blob, sz, &stacksize))
1367 				goto free_areas;
1368 			blob += sz;
1369 			blobsize -= sz;
1370 		} else if (argclass != ARGCLASS_NONE)
1371 			goto free_areas;
1372 		/* walk past the '%' */
1373 		++f;
1374 	}
1375 	if (blobsize) {
1376 		fprintf(stderr, "Couldn't consume all data for format %s "
1377 			"(%zu bytes left over)\n", fmt, blobsize);
1378 		goto free_areas;
1379 	}
1380 	va_list_rewind(valist);
1381 	*_valist = valist;
1382 	return 0;
1383 free_areas:
1384 	if (valist->reg_save_area)
1385 		free(valist->reg_save_area);
1386 	if (valist->overflow_arg_area_save)
1387 		free(valist->overflow_arg_area_save);
1388 free_valist:
1389 	free(valist);
1390 	*_valist = NULL;
1391 	return -1;
1392 }
1393 
1394 #else
1395 #error "Don't know how to get a va_list on this platform"
1396 #endif
1397