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 * $DragonFly: src/usr.bin/ktrdump/ktrdump.c,v 1.13 2008/11/10 02:05:31 swildner Exp $ 29 */ 30 31 #include <sys/cdefs.h> 32 33 #include <sys/types.h> 34 #include <sys/ktr.h> 35 #include <sys/mman.h> 36 #include <sys/stat.h> 37 #include <sys/queue.h> 38 39 #include <ctype.h> 40 #include <devinfo.h> 41 #include <err.h> 42 #include <fcntl.h> 43 #include <kvm.h> 44 #include <limits.h> 45 #include <nlist.h> 46 #include <stdint.h> 47 #include <stdio.h> 48 #include <stdlib.h> 49 #include <string.h> 50 #include <unistd.h> 51 #include <evtr.h> 52 #include <stdarg.h> 53 54 struct ktr_buffer { 55 struct ktr_entry *ents; 56 int modified; 57 int reset; 58 int beg_idx; /* Beginning index */ 59 int end_idx; /* Ending index */ 60 }; 61 62 static struct nlist nl1[] = { 63 { .n_name = "_ktr_version" }, 64 { .n_name = "_ktr_entries" }, 65 { .n_name = "_ncpus" }, 66 { .n_name = NULL } 67 }; 68 69 static struct nlist nl2[] = { 70 { .n_name = "_tsc_frequency" }, 71 { .n_name = NULL } 72 }; 73 74 static struct nlist nl_version_ktr_idx[] = { 75 { .n_name = "_ktr_idx" }, 76 { .n_name = "_ktr_buf" }, 77 { .n_name = NULL } 78 }; 79 80 static struct nlist nl_version_ktr_cpu[] = { 81 { .n_name = "_ktr_cpu" }, 82 { .n_name = NULL } 83 }; 84 85 struct save_ctx { 86 char save_buf[512]; 87 const void *save_kptr; 88 }; 89 90 typedef void (*ktr_iter_cb_t)(void *, int, int, struct ktr_entry *, uint64_t *); 91 92 static int cflag; 93 static int dflag; 94 static int fflag; 95 static int iflag; 96 static int lflag; 97 static int nflag; 98 static int qflag; 99 static int rflag; 100 static int sflag; 101 static int tflag; 102 static int xflag; 103 static int pflag; 104 static int Mflag; 105 static int Nflag; 106 static double tsc_frequency; 107 static double correction_factor = 0.0; 108 109 static char corefile[PATH_MAX]; 110 static char execfile[PATH_MAX]; 111 112 static char errbuf[_POSIX2_LINE_MAX]; 113 static int ncpus; 114 static kvm_t *kd; 115 static int entries_per_buf; 116 static int fifo_mask; 117 static int ktr_version; 118 119 static void usage(void); 120 static int earliest_ts(struct ktr_buffer *); 121 static void dump_machine_info(evtr_t); 122 static void dump_device_info(evtr_t); 123 static void print_header(FILE *, int); 124 static void print_entry(FILE *, int, int, struct ktr_entry *, u_int64_t *); 125 static void print_callback(void *, int, int, struct ktr_entry *, uint64_t *); 126 static void dump_callback(void *, int, int, struct ktr_entry *, uint64_t *); 127 static struct ktr_info *kvm_ktrinfo(void *, struct save_ctx *); 128 static const char *kvm_string(const char *, struct save_ctx *); 129 static const char *trunc_path(const char *, int); 130 static void read_symbols(const char *); 131 static const char *address_to_symbol(void *, struct save_ctx *); 132 static struct ktr_buffer *ktr_bufs_init(void); 133 static void get_indices(struct ktr_entry **, int *); 134 static void load_bufs(struct ktr_buffer *, struct ktr_entry **, int *); 135 static void iterate_buf(FILE *, struct ktr_buffer *, int, u_int64_t *, ktr_iter_cb_t); 136 static void iterate_bufs_timesorted(FILE *, struct ktr_buffer *, u_int64_t *, ktr_iter_cb_t); 137 static void kvmfprintf(FILE *fp, const char *ctl, va_list va); 138 139 /* 140 * Reads the ktr trace buffer from kernel memory and prints the trace entries. 141 */ 142 int 143 main(int ac, char **av) 144 { 145 struct ktr_buffer *ktr_bufs; 146 struct ktr_entry **ktr_kbuf; 147 ktr_iter_cb_t callback = &print_callback; 148 int *ktr_idx; 149 FILE *fo; 150 void *ctx; 151 int64_t tts; 152 int *ktr_start_index; 153 int c; 154 int n; 155 156 /* 157 * Parse commandline arguments. 158 */ 159 fo = stdout; 160 while ((c = getopt(ac, av, "acfinqrtxpslA:N:M:o:d")) != -1) { 161 switch (c) { 162 case 'a': 163 cflag = 1; 164 iflag = 1; 165 rflag = 1; 166 xflag = 1; 167 pflag = 1; 168 sflag = 1; 169 break; 170 case 'c': 171 cflag = 1; 172 break; 173 case 'd': 174 dflag = 1; 175 sflag = 1; 176 callback = &dump_callback; 177 break; 178 case 'N': 179 if (strlcpy(execfile, optarg, sizeof(execfile)) 180 >= sizeof(execfile)) 181 errx(1, "%s: File name too long", optarg); 182 Nflag = 1; 183 break; 184 case 'f': 185 fflag = 1; 186 break; 187 case 'l': 188 lflag = 1; 189 break; 190 case 'i': 191 iflag = 1; 192 break; 193 case 'A': 194 correction_factor = strtod(optarg, NULL); 195 break; 196 case 'M': 197 if (strlcpy(corefile, optarg, sizeof(corefile)) 198 >= sizeof(corefile)) 199 errx(1, "%s: File name too long", optarg); 200 Mflag = 1; 201 break; 202 case 'n': 203 nflag = 1; 204 break; 205 case 'o': 206 if ((fo = fopen(optarg, "w")) == NULL) 207 err(1, "%s", optarg); 208 break; 209 case 'p': 210 pflag++; 211 break; 212 case 'q': 213 qflag++; 214 break; 215 case 'r': 216 rflag = 1; 217 break; 218 case 's': 219 sflag = 1; /* sort across the cpus */ 220 break; 221 case 't': 222 tflag = 1; 223 break; 224 case 'x': 225 xflag = 1; 226 break; 227 case '?': 228 default: 229 usage(); 230 } 231 } 232 ctx = fo; 233 if (dflag) { 234 ctx = evtr_open_write(fo); 235 if (!ctx) { 236 err(1, "Can't create event stream"); 237 } 238 } 239 if (cflag + iflag + tflag + xflag + fflag + pflag == 0) { 240 cflag = 1; 241 iflag = 1; 242 tflag = 1; 243 pflag = 1; 244 } 245 if (correction_factor != 0.0 && (rflag == 0 || nflag)) { 246 fprintf(stderr, "Correction factor can only be applied with -r and without -n\n"); 247 exit(1); 248 } 249 ac -= optind; 250 av += optind; 251 if (ac != 0) 252 usage(); 253 254 /* 255 * Open our execfile and corefile, resolve needed symbols and read in 256 * the trace buffer. 257 */ 258 if ((kd = kvm_openfiles(Nflag ? execfile : NULL, 259 Mflag ? corefile : NULL, NULL, O_RDONLY, errbuf)) == NULL) 260 errx(1, "%s", errbuf); 261 if (kvm_nlist(kd, nl1) != 0) 262 errx(1, "%s", kvm_geterr(kd)); 263 if (kvm_read(kd, nl1[0].n_value, &ktr_version, sizeof(ktr_version)) == -1) 264 errx(1, "%s", kvm_geterr(kd)); 265 if (kvm_read(kd, nl1[2].n_value, &ncpus, sizeof(ncpus)) == -1) 266 errx(1, "%s", kvm_geterr(kd)); 267 ktr_start_index = malloc(sizeof(*ktr_start_index) * ncpus); 268 if (ktr_version >= KTR_VERSION_WITH_FREQ && kvm_nlist(kd, nl2) == 0) { 269 if (kvm_read(kd, nl2[0].n_value, &tts, sizeof(tts)) == -1) 270 errx(1, "%s", kvm_geterr(kd)); 271 tsc_frequency = (double)tts; 272 } 273 if (ktr_version > KTR_VERSION) 274 errx(1, "ktr version too high for us to handle"); 275 if (kvm_read(kd, nl1[1].n_value, &entries_per_buf, 276 sizeof(entries_per_buf)) == -1) 277 errx(1, "%s", kvm_geterr(kd)); 278 fifo_mask = entries_per_buf - 1; 279 280 printf("TSC frequency is %6.3f MHz\n", tsc_frequency / 1000000.0); 281 282 if (dflag) { 283 dump_machine_info((evtr_t)ctx); 284 dump_device_info((evtr_t)ctx); 285 } 286 ktr_kbuf = calloc(ncpus, sizeof(*ktr_kbuf)); 287 ktr_idx = calloc(ncpus, sizeof(*ktr_idx)); 288 289 if (nflag == 0) 290 read_symbols(Nflag ? execfile : NULL); 291 292 if (ktr_version < KTR_VERSION_KTR_CPU) { 293 if (kvm_nlist(kd, nl_version_ktr_idx)) 294 errx(1, "%s", kvm_geterr(kd)); 295 } else { 296 if (kvm_nlist(kd, nl_version_ktr_cpu)) 297 errx(1, "%s", kvm_geterr(kd)); 298 } 299 300 get_indices(ktr_kbuf, ktr_idx); 301 302 ktr_bufs = ktr_bufs_init(); 303 304 if (sflag) { 305 u_int64_t last_timestamp = 0; 306 do { 307 load_bufs(ktr_bufs, ktr_kbuf, ktr_idx); 308 iterate_bufs_timesorted(ctx, ktr_bufs, &last_timestamp, 309 callback); 310 if (lflag) 311 usleep(1000000 / 10); 312 } while (lflag); 313 } else { 314 u_int64_t *last_timestamp = calloc(sizeof(u_int64_t), ncpus); 315 do { 316 load_bufs(ktr_bufs, ktr_kbuf, ktr_idx); 317 for (n = 0; n < ncpus; ++n) 318 iterate_buf(ctx, ktr_bufs, n, &last_timestamp[n], 319 callback); 320 if (lflag) 321 usleep(1000000 / 10); 322 } while (lflag); 323 } 324 if (dflag) 325 evtr_close(ctx); 326 return (0); 327 } 328 329 static 330 int 331 dump_devinfo(struct devinfo_dev *dev, void *arg) 332 { 333 struct evtr_event ev; 334 evtr_t evtr = (evtr_t)arg; 335 const char *fmt = "#devicenames[\"%s\"] = %#lx"; 336 char fmtdatabuf[sizeof(char *) + sizeof(devinfo_handle_t)]; 337 char *fmtdata = fmtdatabuf; 338 339 if (!dev->dd_name[0]) 340 return 0; 341 ev.type = EVTR_TYPE_PROBE; 342 ev.ts = 0; 343 ev.line = 0; 344 ev.file = NULL; 345 ev.cpu = -1; 346 ev.func = NULL; 347 ev.fmt = fmt; 348 ((char **)fmtdata)[0] = &dev->dd_name[0]; 349 fmtdata += sizeof(char *); 350 ((devinfo_handle_t *)fmtdata)[0] = dev->dd_handle; 351 ev.fmtdata = fmtdatabuf; 352 ev.fmtdatalen = sizeof(fmtdatabuf); 353 354 if (evtr_dump_event(evtr, &ev)) { 355 err(1, evtr_errmsg(evtr)); 356 } 357 358 return devinfo_foreach_device_child(dev, dump_devinfo, evtr); 359 } 360 361 static 362 void 363 dump_device_info(evtr_t evtr) 364 { 365 struct devinfo_dev *root; 366 if (devinfo_init()) 367 return; 368 if (!(root = devinfo_handle_to_device(DEVINFO_ROOT_DEVICE))) { 369 warn("can't find root device"); 370 return; 371 } 372 devinfo_foreach_device_child(root, dump_devinfo, evtr); 373 } 374 375 static 376 void 377 dump_machine_info(evtr_t evtr) 378 { 379 struct evtr_event ev; 380 int i; 381 382 bzero(&ev, sizeof(ev)); 383 ev.type = EVTR_TYPE_SYSINFO; 384 ev.ncpus = ncpus; 385 evtr_dump_event(evtr, &ev); 386 if (evtr_error(evtr)) { 387 err(1, evtr_errmsg(evtr)); 388 } 389 390 for (i = 0; i < ncpus; ++i) { 391 bzero(&ev, sizeof(ev)); 392 ev.type = EVTR_TYPE_CPUINFO; 393 ev.cpu = i; 394 ev.cpuinfo.freq = tsc_frequency; 395 evtr_dump_event(evtr, &ev); 396 if (evtr_error(evtr)) { 397 err(1, evtr_errmsg(evtr)); 398 } 399 } 400 } 401 402 static void 403 print_header(FILE *fo, int row) 404 { 405 if (qflag == 0 && (u_int32_t)row % 20 == 0) { 406 fprintf(fo, "%-6s ", "index"); 407 if (cflag) 408 fprintf(fo, "%-3s ", "cpu"); 409 if (tflag || rflag) 410 fprintf(fo, "%-16s ", "timestamp"); 411 if (xflag) { 412 if (nflag) 413 fprintf(fo, "%-10s %-10s", "caller2", "caller1"); 414 else 415 fprintf(fo, "%-20s %-20s", "caller2", "caller1"); 416 } 417 if (iflag) 418 fprintf(fo, "%-20s ", "ID"); 419 if (fflag) 420 fprintf(fo, "%10s%-30s ", "", "file and line"); 421 if (pflag) 422 fprintf(fo, "%s", "trace"); 423 fprintf(fo, "\n"); 424 } 425 } 426 427 static void 428 print_entry(FILE *fo, int n, int row, struct ktr_entry *entry, 429 u_int64_t *last_timestamp) 430 { 431 struct ktr_info *info = NULL; 432 static struct save_ctx nctx, pctx, fmtctx, symctx, infoctx; 433 434 fprintf(fo, " %06x ", row & 0x00FFFFFF); 435 if (cflag) 436 fprintf(fo, "%-3d ", n); 437 if (tflag || rflag) { 438 if (rflag && !nflag && tsc_frequency != 0.0) { 439 fprintf(fo, "%13.3f uS ", 440 (double)(entry->ktr_timestamp - *last_timestamp) * 1000000.0 / tsc_frequency - correction_factor); 441 } else if (rflag) { 442 fprintf(fo, "%-16ju ", 443 (uintmax_t)(entry->ktr_timestamp - *last_timestamp)); 444 } else { 445 fprintf(fo, "%-16ju ", 446 (uintmax_t)entry->ktr_timestamp); 447 } 448 } 449 if (xflag) { 450 if (nflag) { 451 fprintf(fo, "%p %p ", 452 entry->ktr_caller2, entry->ktr_caller1); 453 } else { 454 fprintf(fo, "%-25s ", 455 address_to_symbol(entry->ktr_caller2, &symctx)); 456 fprintf(fo, "%-25s ", 457 address_to_symbol(entry->ktr_caller1, &symctx)); 458 } 459 } 460 if (iflag) { 461 info = kvm_ktrinfo(entry->ktr_info, &infoctx); 462 if (info) 463 fprintf(fo, "%-20s ", kvm_string(info->kf_name, &nctx)); 464 else 465 fprintf(fo, "%-20s ", "<empty>"); 466 } 467 if (fflag) 468 fprintf(fo, "%34s:%-4d ", 469 trunc_path(kvm_string(entry->ktr_file, &pctx), 34), 470 entry->ktr_line); 471 if (pflag) { 472 if (info == NULL) 473 info = kvm_ktrinfo(entry->ktr_info, &infoctx); 474 if (info) 475 kvmfprintf(fo, kvm_string(info->kf_format, &fmtctx), 476 (void *)&entry->ktr_data); 477 } 478 fprintf(fo, "\n"); 479 *last_timestamp = entry->ktr_timestamp; 480 } 481 482 static 483 void 484 print_callback(void *ctx, int n, int row, struct ktr_entry *entry, uint64_t *last_ts) 485 { 486 FILE *fo = (FILE *)ctx; 487 print_header(fo, row); 488 print_entry(fo, n, row, entry, last_ts); 489 } 490 491 /* 492 * If free == 0, replace all (kvm) string pointers in fmtdata with pointers 493 * to user-allocated copies of the strings. 494 * If free != 0, free those pointers. 495 */ 496 static 497 int 498 mangle_string_ptrs(const char *fmt, uint8_t *fmtdata, int dofree) 499 { 500 const char *f, *p; 501 size_t skipsize, intsz; 502 static struct save_ctx strctx; 503 int ret = 0; 504 505 for (f = fmt; f[0] != '\0'; ++f) { 506 if (f[0] != '%') 507 continue; 508 ++f; 509 skipsize = 0; 510 for (p = f; p[0]; ++p) { 511 int again = 0; 512 /* 513 * Eat flags. Notice this will accept duplicate 514 * flags. 515 */ 516 switch (p[0]) { 517 case '#': 518 case '0': 519 case '-': 520 case ' ': 521 case '+': 522 case '\'': 523 again = !0; 524 break; 525 } 526 if (!again) 527 break; 528 } 529 /* Eat minimum field width, if any */ 530 for (; isdigit(p[0]); ++p) 531 ; 532 if (p[0] == '.') 533 ++p; 534 /* Eat precision, if any */ 535 for (; isdigit(p[0]); ++p) 536 ; 537 intsz = 0; 538 switch (p[0]) { 539 case 'l': 540 if (p[1] == 'l') { 541 ++p; 542 intsz = sizeof(long long); 543 } else { 544 intsz = sizeof(long); 545 } 546 break; 547 case 'j': 548 intsz = sizeof(intmax_t); 549 break; 550 case 't': 551 intsz = sizeof(ptrdiff_t); 552 break; 553 case 'z': 554 intsz = sizeof(size_t); 555 break; 556 default: 557 break; 558 } 559 if (intsz != 0) 560 ++p; 561 else 562 intsz = sizeof(int); 563 564 switch (p[0]) { 565 case 'd': 566 case 'i': 567 case 'o': 568 case 'u': 569 case 'x': 570 case 'X': 571 case 'c': 572 skipsize = intsz; 573 break; 574 case 'p': 575 skipsize = sizeof(void *); 576 break; 577 case 'f': 578 if (p[-1] == 'l') 579 skipsize = sizeof(double); 580 else 581 skipsize = sizeof(float); 582 break; 583 case 's': 584 if (dofree) { 585 char *t = ((char **)fmtdata)[0]; 586 free(t); 587 skipsize = sizeof(char *); 588 } else { 589 char *t = strdup(kvm_string(((char **)fmtdata)[0], 590 &strctx)); 591 ((const char **)fmtdata)[0] = t; 592 593 skipsize = sizeof(char *); 594 } 595 ++ret; 596 break; 597 default: 598 fprintf(stderr, "Unknown conversion specifier %c " 599 "in fmt starting with %s", p[0], f - 1); 600 return -1; 601 } 602 fmtdata += skipsize; 603 } 604 return ret; 605 } 606 607 static 608 void 609 dump_callback(void *ctx, int n, int row __unused, struct ktr_entry *entry, 610 uint64_t *last_ts __unused) 611 { 612 evtr_t evtr = (evtr_t)ctx; 613 struct evtr_event ev; 614 static struct save_ctx pctx, fmtctx, infoctx; 615 struct ktr_info *ki; 616 int conv = 0; /* pointless */ 617 618 ev.ts = entry->ktr_timestamp; 619 ev.type = EVTR_TYPE_PROBE; 620 ev.line = entry->ktr_line; 621 ev.file = kvm_string(entry->ktr_file, &pctx); 622 ev.func = NULL; 623 ev.cpu = n; 624 if ((ki = kvm_ktrinfo(entry->ktr_info, &infoctx))) { 625 ev.fmt = kvm_string(ki->kf_format, &fmtctx); 626 ev.fmtdata = entry->ktr_data; 627 if ((conv = mangle_string_ptrs(ev.fmt, 628 __DECONST(uint8_t *, ev.fmtdata), 629 0)) < 0) 630 errx(1, "Can't parse format string\n"); 631 ev.fmtdatalen = ki->kf_data_size; 632 } else { 633 ev.fmt = ev.fmtdata = NULL; 634 ev.fmtdatalen = 0; 635 } 636 if (evtr_dump_event(evtr, &ev)) { 637 err(1, evtr_errmsg(evtr)); 638 } 639 if (ev.fmtdata && conv) { 640 mangle_string_ptrs(ev.fmt, __DECONST(uint8_t *, ev.fmtdata), 641 !0); 642 } 643 } 644 645 static 646 struct ktr_info * 647 kvm_ktrinfo(void *kptr, struct save_ctx *ctx) 648 { 649 struct ktr_info *ki = (void *)ctx->save_buf; 650 651 if (kptr == NULL) 652 return(NULL); 653 if (ctx->save_kptr != kptr) { 654 if (kvm_read(kd, (uintptr_t)kptr, ki, sizeof(*ki)) == -1) { 655 bzero(&ki, sizeof(*ki)); 656 } else { 657 ctx->save_kptr = kptr; 658 } 659 } 660 return(ki); 661 } 662 663 static 664 const char * 665 kvm_string(const char *kptr, struct save_ctx *ctx) 666 { 667 u_int l; 668 u_int n; 669 670 if (kptr == NULL) 671 return("?"); 672 if (ctx->save_kptr != (const void *)kptr) { 673 ctx->save_kptr = (const void *)kptr; 674 l = 0; 675 while (l < sizeof(ctx->save_buf) - 1) { 676 n = 256 - ((intptr_t)(kptr + l) & 255); 677 if (n > sizeof(ctx->save_buf) - l - 1) 678 n = sizeof(ctx->save_buf) - l - 1; 679 if (kvm_read(kd, (uintptr_t)(kptr + l), ctx->save_buf + l, n) < 0) 680 break; 681 while (l < sizeof(ctx->save_buf) && n) { 682 if (ctx->save_buf[l] == 0) 683 break; 684 --n; 685 ++l; 686 } 687 if (n) 688 break; 689 } 690 ctx->save_buf[l] = 0; 691 } 692 return(ctx->save_buf); 693 } 694 695 static 696 const char * 697 trunc_path(const char *str, int maxlen) 698 { 699 int len = strlen(str); 700 701 if (len > maxlen) 702 return(str + len - maxlen); 703 else 704 return(str); 705 } 706 707 struct symdata { 708 TAILQ_ENTRY(symdata) link; 709 const char *symname; 710 char *symaddr; 711 char symtype; 712 }; 713 714 static TAILQ_HEAD(symlist, symdata) symlist; 715 static struct symdata *symcache; 716 static char *symbegin; 717 static char *symend; 718 719 static 720 void 721 read_symbols(const char *file) 722 { 723 char buf[256]; 724 char cmd[256]; 725 size_t buflen = sizeof(buf); 726 FILE *fp; 727 struct symdata *sym; 728 char *s1; 729 char *s2; 730 char *s3; 731 732 TAILQ_INIT(&symlist); 733 734 if (file == NULL) { 735 if (sysctlbyname("kern.bootfile", buf, &buflen, NULL, 0) < 0) 736 file = "/boot/kernel"; 737 else 738 file = buf; 739 } 740 snprintf(cmd, sizeof(cmd), "nm -n %s", file); 741 if ((fp = popen(cmd, "r")) != NULL) { 742 while (fgets(buf, sizeof(buf), fp) != NULL) { 743 s1 = strtok(buf, " \t\n"); 744 s2 = strtok(NULL, " \t\n"); 745 s3 = strtok(NULL, " \t\n"); 746 if (s1 && s2 && s3) { 747 sym = malloc(sizeof(struct symdata)); 748 sym->symaddr = (char *)strtoul(s1, NULL, 16); 749 sym->symtype = s2[0]; 750 sym->symname = strdup(s3); 751 if (strcmp(s3, "kernbase") == 0) 752 symbegin = sym->symaddr; 753 if (strcmp(s3, "end") == 0) 754 symend = sym->symaddr; 755 TAILQ_INSERT_TAIL(&symlist, sym, link); 756 } 757 } 758 pclose(fp); 759 } 760 symcache = TAILQ_FIRST(&symlist); 761 } 762 763 static 764 const char * 765 address_to_symbol(void *kptr, struct save_ctx *ctx) 766 { 767 char *buf = ctx->save_buf; 768 int size = sizeof(ctx->save_buf); 769 770 if (symcache == NULL || 771 (char *)kptr < symbegin || (char *)kptr >= symend 772 ) { 773 snprintf(buf, size, "%p", kptr); 774 return(buf); 775 } 776 while ((char *)symcache->symaddr < (char *)kptr) { 777 if (TAILQ_NEXT(symcache, link) == NULL) 778 break; 779 symcache = TAILQ_NEXT(symcache, link); 780 } 781 while ((char *)symcache->symaddr > (char *)kptr) { 782 if (symcache != TAILQ_FIRST(&symlist)) 783 symcache = TAILQ_PREV(symcache, symlist, link); 784 } 785 snprintf(buf, size, "%s+%d", symcache->symname, 786 (int)((char *)kptr - symcache->symaddr)); 787 return(buf); 788 } 789 790 static 791 struct ktr_buffer * 792 ktr_bufs_init(void) 793 { 794 struct ktr_buffer *ktr_bufs, *it; 795 int i; 796 797 ktr_bufs = malloc(sizeof(*ktr_bufs) * ncpus); 798 if (!ktr_bufs) 799 err(1, "can't allocate data structures\n"); 800 for (i = 0; i < ncpus; ++i) { 801 it = ktr_bufs + i; 802 it->ents = malloc(sizeof(struct ktr_entry) * entries_per_buf); 803 if (it->ents == NULL) 804 err(1, "can't allocate data structures\n"); 805 it->reset = 1; 806 it->beg_idx = -1; 807 it->end_idx = -1; 808 } 809 return ktr_bufs; 810 } 811 812 static 813 void 814 get_indices(struct ktr_entry **ktr_kbuf, int *ktr_idx) 815 { 816 static struct ktr_cpu *ktr_cpus; 817 int i; 818 819 if (ktr_cpus == NULL) 820 ktr_cpus = malloc(sizeof(*ktr_cpus) * ncpus); 821 822 if (ktr_version < KTR_VERSION_KTR_CPU) { 823 if (kvm_read(kd, nl_version_ktr_idx[0].n_value, ktr_idx, 824 sizeof(*ktr_idx) * ncpus) == -1) { 825 errx(1, "%s", kvm_geterr(kd)); 826 } 827 if (ktr_kbuf[0] == NULL) { 828 if (kvm_read(kd, nl_version_ktr_idx[1].n_value, 829 ktr_kbuf, sizeof(*ktr_kbuf) * ncpus) == -1) { 830 errx(1, "%s", kvm_geterr(kd)); 831 } 832 } 833 } else { 834 if (kvm_read(kd, nl_version_ktr_cpu[0].n_value, 835 ktr_cpus, sizeof(*ktr_cpus) * ncpus) == -1) { 836 errx(1, "%s", kvm_geterr(kd)); 837 } 838 for (i = 0; i < ncpus; ++i) { 839 ktr_idx[i] = ktr_cpus[i].core.ktr_idx; 840 ktr_kbuf[i] = ktr_cpus[i].core.ktr_buf; 841 } 842 } 843 } 844 845 /* 846 * Get the trace buffer data from the kernel 847 */ 848 static 849 void 850 load_bufs(struct ktr_buffer *ktr_bufs, struct ktr_entry **kbufs, int *ktr_idx) 851 { 852 struct ktr_buffer *kbuf; 853 int i; 854 855 get_indices(kbufs, ktr_idx); 856 for (i = 0; i < ncpus; ++i) { 857 kbuf = &ktr_bufs[i]; 858 if (ktr_idx[i] == kbuf->end_idx) 859 continue; 860 kbuf->end_idx = ktr_idx[i]; 861 862 /* 863 * If we do not have a notion of the beginning index, assume 864 * it is entries_per_buf before the ending index. Don't 865 * worry about underflows/negative numbers, the indices will 866 * be masked. 867 */ 868 if (kbuf->reset) { 869 kbuf->beg_idx = kbuf->end_idx - entries_per_buf + 1; 870 kbuf->reset = 0; 871 } 872 if (kvm_read(kd, (uintptr_t)kbufs[i], ktr_bufs[i].ents, 873 sizeof(struct ktr_entry) * entries_per_buf) 874 == -1) 875 errx(1, "%s", kvm_geterr(kd)); 876 kbuf->modified = 1; 877 kbuf->beg_idx = earliest_ts(kbuf); 878 } 879 880 } 881 882 /* 883 * Locate the earliest timestamp iterating backwards from end_idx, but 884 * not going further back then beg_idx. We have to do this because 885 * the kernel uses a circulating buffer. 886 */ 887 static 888 int 889 earliest_ts(struct ktr_buffer *buf) 890 { 891 struct ktr_entry *save; 892 int count, scan, i, earliest; 893 894 count = 0; 895 earliest = buf->end_idx - 1; 896 save = &buf->ents[earliest & fifo_mask]; 897 for (scan = buf->end_idx - 1; scan != buf->beg_idx -1; --scan) { 898 i = scan & fifo_mask; 899 if (buf->ents[i].ktr_timestamp <= save->ktr_timestamp && 900 buf->ents[i].ktr_timestamp > 0) 901 earliest = scan; 902 /* 903 * We may have gotten so far behind that beg_idx wrapped 904 * more then once around the buffer. Just stop 905 */ 906 if (++count == entries_per_buf) 907 break; 908 } 909 return earliest; 910 } 911 912 static 913 void 914 iterate_buf(FILE *fo, struct ktr_buffer *ktr_bufs, int cpu, 915 u_int64_t *last_timestamp, ktr_iter_cb_t cb) 916 { 917 struct ktr_buffer *buf = ktr_bufs + cpu; 918 919 if (buf->modified == 0) 920 return; 921 if (*last_timestamp == 0) { 922 *last_timestamp = 923 buf->ents[buf->beg_idx & fifo_mask].ktr_timestamp; 924 } 925 while (buf->beg_idx != buf->end_idx) { 926 cb(fo, cpu, buf->beg_idx, 927 &buf->ents[buf->beg_idx & fifo_mask], 928 last_timestamp); 929 ++buf->beg_idx; 930 } 931 buf->modified = 0; 932 } 933 934 static 935 void 936 iterate_bufs_timesorted(FILE *fo, struct ktr_buffer *ktr_bufs, 937 u_int64_t *last_timestamp, ktr_iter_cb_t cb) 938 { 939 struct ktr_entry *ent; 940 struct ktr_buffer *buf; 941 int n, bestn; 942 u_int64_t ts; 943 static int row = 0; 944 945 for (;;) { 946 ts = 0; 947 bestn = -1; 948 for (n = 0; n < ncpus; ++n) { 949 buf = ktr_bufs + n; 950 if (buf->beg_idx == buf->end_idx) 951 continue; 952 ent = &buf->ents[buf->beg_idx & fifo_mask]; 953 if (ts == 0 || (ts >= ent->ktr_timestamp)) { 954 ts = ent->ktr_timestamp; 955 bestn = n; 956 } 957 } 958 if ((bestn < 0) || (ts < *last_timestamp)) 959 break; 960 buf = ktr_bufs + bestn; 961 cb(fo, bestn, row, 962 &buf->ents[buf->beg_idx & fifo_mask], 963 last_timestamp); 964 ++buf->beg_idx; 965 *last_timestamp = ts; 966 ++row; 967 } 968 } 969 970 static 971 void 972 kvmfprintf(FILE *fp, const char *ctl, va_list va) 973 { 974 int n; 975 int is_long; 976 int is_done; 977 char fmt[256]; 978 static struct save_ctx strctx; 979 const char *s; 980 981 while (*ctl) { 982 for (n = 0; ctl[n]; ++n) { 983 fmt[n] = ctl[n]; 984 if (ctl[n] == '%') 985 break; 986 } 987 if (n == 0) { 988 is_long = 0; 989 is_done = 0; 990 n = 1; 991 while (n < (int)sizeof(fmt)) { 992 fmt[n] = ctl[n]; 993 fmt[n+1] = 0; 994 995 switch(ctl[n]) { 996 case 'p': 997 is_long = 1; 998 /* fall through */ 999 case 'd': 1000 case 'u': 1001 case 'x': 1002 case 'o': 1003 case 'X': 1004 /* 1005 * Integral 1006 */ 1007 switch(is_long) { 1008 case 0: 1009 fprintf(fp, fmt, 1010 va_arg(va, int)); 1011 break; 1012 case 1: 1013 fprintf(fp, fmt, 1014 va_arg(va, long)); 1015 break; 1016 case 2: 1017 fprintf(fp, fmt, 1018 va_arg(va, long long)); 1019 break; 1020 case 3: 1021 fprintf(fp, fmt, 1022 va_arg(va, size_t)); 1023 break; 1024 } 1025 ++n; 1026 is_done = 1; 1027 break; 1028 case 's': 1029 /* 1030 * String 1031 */ 1032 s = kvm_string(va_arg(va, char *), &strctx); 1033 fwrite(s, 1, strlen(s), fp); 1034 ++n; 1035 is_done = 1; 1036 break; 1037 case 'f': 1038 /* 1039 * Floating 1040 */ 1041 fprintf(fp, fmt, 1042 va_arg(va, double)); 1043 ++n; 1044 break; 1045 case 'j': 1046 is_long = 3; 1047 break; 1048 case 'l': 1049 if (is_long) 1050 is_long = 2; 1051 else 1052 is_long = 1; 1053 break; 1054 case '.': 1055 case '-': 1056 case '+': 1057 case '0': 1058 case '1': 1059 case '2': 1060 case '3': 1061 case '4': 1062 case '5': 1063 case '6': 1064 case '7': 1065 case '8': 1066 case '9': 1067 break; 1068 default: 1069 is_done = 1; 1070 break; 1071 } 1072 if (is_done) 1073 break; 1074 ++n; 1075 } 1076 } else { 1077 fmt[n] = 0; 1078 fprintf(fp, fmt, NULL); 1079 } 1080 ctl += n; 1081 } 1082 } 1083 1084 static void 1085 usage(void) 1086 { 1087 fprintf(stderr, "usage: ktrdump [-acfilnpqrstx] [-A factor] " 1088 "[-N execfile] [-M corefile] [-o outfile]\n"); 1089 exit(1); 1090 } 1091