7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /*
27 * Copyright (c) 2011, Joyent, Inc. All rights reserved.
28 * Copyright (c) 2012 by Delphix. All rights reserved.
29 */
30
31 #include <stdlib.h>
32 #include <strings.h>
33 #include <errno.h>
34 #include <unistd.h>
35 #include <limits.h>
36 #include <assert.h>
37 #include <ctype.h>
38 #include <alloca.h>
39 #include <dt_impl.h>
40 #include <dt_pq.h>
41
42 #define DT_MASK_LO 0x00000000FFFFFFFFULL
43
44 /*
45 * We declare this here because (1) we need it and (2) we want to avoid a
46 * dependency on libm in libdtrace.
47 */
48 static long double
49 dt_fabsl(long double x)
50 {
51 if (x < 0)
52 return (-x);
53
54 return (x);
55 }
56
57 /*
58 * 128-bit arithmetic functions needed to support the stddev() aggregating
59 * action.
60 */
61 static int
62 dt_gt_128(uint64_t *a, uint64_t *b)
63 {
64 return (a[1] > b[1] || (a[1] == b[1] && a[0] > b[0]));
65 }
66
67 static int
68 dt_ge_128(uint64_t *a, uint64_t *b)
69 {
70 return (a[1] > b[1] || (a[1] == b[1] && a[0] >= b[0]));
71 }
72
73 static int
74 dt_le_128(uint64_t *a, uint64_t *b)
75 {
76 return (a[1] < b[1] || (a[1] == b[1] && a[0] <= b[0]));
465 if (flow == DTRACEFLOW_RETURN && data->dtpda_indent > 0)
466 data->dtpda_indent -= 2;
467
468 data->dtpda_flow = flow;
469
470 return (0);
471 }
472
473 static int
474 dt_nullprobe()
475 {
476 return (DTRACE_CONSUME_THIS);
477 }
478
479 static int
480 dt_nullrec()
481 {
482 return (DTRACE_CONSUME_NEXT);
483 }
484
485 int
486 dt_print_quantline(dtrace_hdl_t *dtp, FILE *fp, int64_t val,
487 uint64_t normal, long double total, char positives, char negatives)
488 {
489 long double f;
490 uint_t depth, len = 40;
491
492 const char *ats = "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@";
493 const char *spaces = " ";
494
495 assert(strlen(ats) == len && strlen(spaces) == len);
496 assert(!(total == 0 && (positives || negatives)));
497 assert(!(val < 0 && !negatives));
498 assert(!(val > 0 && !positives));
499 assert(!(val != 0 && total == 0));
500
501 if (!negatives) {
502 if (positives) {
503 f = (dt_fabsl((long double)val) * len) / total;
504 depth = (uint_t)(f + 0.5);
505 } else {
506 depth = 0;
507 }
508
509 return (dt_printf(dtp, fp, "|%s%s %-9lld\n", ats + len - depth,
510 spaces + depth, (long long)val / normal));
511 }
512
513 if (!positives) {
514 f = (dt_fabsl((long double)val) * len) / total;
515 depth = (uint_t)(f + 0.5);
516
517 return (dt_printf(dtp, fp, "%s%s| %-9lld\n", spaces + depth,
518 ats + len - depth, (long long)val / normal));
519 }
520
521 /*
522 * If we're here, we have both positive and negative bucket values.
525 * the size of normal quantize()/lquantize() bars, so we divide the
526 * length in half before calculating the bar length.
527 */
528 len /= 2;
529 ats = &ats[len];
530 spaces = &spaces[len];
531
532 f = (dt_fabsl((long double)val) * len) / total;
533 depth = (uint_t)(f + 0.5);
534
535 if (val <= 0) {
536 return (dt_printf(dtp, fp, "%s%s|%*s %-9lld\n", spaces + depth,
537 ats + len - depth, len, "", (long long)val / normal));
538 } else {
539 return (dt_printf(dtp, fp, "%20s|%s%s %-9lld\n", "",
540 ats + len - depth, spaces + depth,
541 (long long)val / normal));
542 }
543 }
544
545 int
546 dt_print_quantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
547 size_t size, uint64_t normal)
548 {
549 const int64_t *data = addr;
550 int i, first_bin = 0, last_bin = DTRACE_QUANTIZE_NBUCKETS - 1;
551 long double total = 0;
552 char positives = 0, negatives = 0;
553
554 if (size != DTRACE_QUANTIZE_NBUCKETS * sizeof (uint64_t))
555 return (dt_set_errno(dtp, EDT_DMISMATCH));
556
557 while (first_bin < DTRACE_QUANTIZE_NBUCKETS - 1 && data[first_bin] == 0)
558 first_bin++;
559
560 if (first_bin == DTRACE_QUANTIZE_NBUCKETS - 1) {
561 /*
562 * There isn't any data. This is possible if (and only if)
563 * negative increment values have been used. In this case,
564 * we'll print the buckets around 0.
565 */
566 first_bin = DTRACE_QUANTIZE_ZEROBUCKET - 1;
567 last_bin = DTRACE_QUANTIZE_ZEROBUCKET + 1;
568 } else {
569 if (first_bin > 0)
570 first_bin--;
571
572 while (last_bin > 0 && data[last_bin] == 0)
573 last_bin--;
574
575 if (last_bin < DTRACE_QUANTIZE_NBUCKETS - 1)
576 last_bin++;
577 }
578
579 for (i = first_bin; i <= last_bin; i++) {
580 positives |= (data[i] > 0);
581 negatives |= (data[i] < 0);
582 total += dt_fabsl((long double)data[i]);
583 }
584
585 if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value",
586 "------------- Distribution -------------", "count") < 0)
587 return (-1);
588
589 for (i = first_bin; i <= last_bin; i++) {
590 if (dt_printf(dtp, fp, "%16lld ",
591 (long long)DTRACE_QUANTIZE_BUCKETVAL(i)) < 0)
592 return (-1);
593
594 if (dt_print_quantline(dtp, fp, data[i], normal, total,
595 positives, negatives) < 0)
596 return (-1);
597 }
598
599 return (0);
600 }
601
602 int
603 dt_print_lquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
604 size_t size, uint64_t normal)
605 {
606 const int64_t *data = addr;
607 int i, first_bin, last_bin, base;
608 uint64_t arg;
609 long double total = 0;
610 uint16_t step, levels;
611 char positives = 0, negatives = 0;
612
613 if (size < sizeof (uint64_t))
614 return (dt_set_errno(dtp, EDT_DMISMATCH));
615
616 arg = *data++;
617 size -= sizeof (uint64_t);
618
619 base = DTRACE_LQUANTIZE_BASE(arg);
620 step = DTRACE_LQUANTIZE_STEP(arg);
621 levels = DTRACE_LQUANTIZE_LEVELS(arg);
622
629 while (first_bin <= levels + 1 && data[first_bin] == 0)
630 first_bin++;
631
632 if (first_bin > levels + 1) {
633 first_bin = 0;
634 last_bin = 2;
635 } else {
636 if (first_bin > 0)
637 first_bin--;
638
639 while (last_bin > 0 && data[last_bin] == 0)
640 last_bin--;
641
642 if (last_bin < levels + 1)
643 last_bin++;
644 }
645
646 for (i = first_bin; i <= last_bin; i++) {
647 positives |= (data[i] > 0);
648 negatives |= (data[i] < 0);
649 total += dt_fabsl((long double)data[i]);
650 }
651
652 if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value",
653 "------------- Distribution -------------", "count") < 0)
654 return (-1);
655
656 for (i = first_bin; i <= last_bin; i++) {
657 char c[32];
658 int err;
659
660 if (i == 0) {
661 (void) snprintf(c, sizeof (c), "< %d",
662 base / (uint32_t)normal);
663 err = dt_printf(dtp, fp, "%16s ", c);
664 } else if (i == levels + 1) {
665 (void) snprintf(c, sizeof (c), ">= %d",
666 base + (levels * step));
667 err = dt_printf(dtp, fp, "%16s ", c);
668 } else {
669 err = dt_printf(dtp, fp, "%16d ",
670 base + (i - 1) * step);
671 }
672
673 if (err < 0 || dt_print_quantline(dtp, fp, data[i], normal,
674 total, positives, negatives) < 0)
675 return (-1);
676 }
677
678 return (0);
679 }
680
681 int
682 dt_print_llquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
683 size_t size, uint64_t normal)
684 {
685 int i, first_bin, last_bin, bin = 1, order, levels;
686 uint16_t factor, low, high, nsteps;
687 const int64_t *data = addr;
688 int64_t value = 1, next, step;
689 char positives = 0, negatives = 0;
690 long double total = 0;
691 uint64_t arg;
692 char c[32];
693
694 if (size < sizeof (uint64_t))
695 return (dt_set_errno(dtp, EDT_DMISMATCH));
696
697 arg = *data++;
698 size -= sizeof (uint64_t);
699
700 factor = DTRACE_LLQUANTIZE_FACTOR(arg);
718 while (first_bin < levels && data[first_bin] == 0)
719 first_bin++;
720
721 if (first_bin == levels) {
722 first_bin = 0;
723 last_bin = 1;
724 } else {
725 if (first_bin > 0)
726 first_bin--;
727
728 while (last_bin > 0 && data[last_bin] == 0)
729 last_bin--;
730
731 if (last_bin < levels - 1)
732 last_bin++;
733 }
734
735 for (i = first_bin; i <= last_bin; i++) {
736 positives |= (data[i] > 0);
737 negatives |= (data[i] < 0);
738 total += dt_fabsl((long double)data[i]);
739 }
740
741 if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value",
742 "------------- Distribution -------------", "count") < 0)
743 return (-1);
744
745 for (order = 0; order < low; order++)
746 value *= factor;
747
748 next = value * factor;
749 step = next > nsteps ? next / nsteps : 1;
750
751 if (first_bin == 0) {
752 (void) snprintf(c, sizeof (c), "< %lld", value);
753
754 if (dt_printf(dtp, fp, "%16s ", c) < 0)
755 return (-1);
756
757 if (dt_print_quantline(dtp, fp, data[0], normal,
758 total, positives, negatives) < 0)
801 /* LINTED - alignment */
802 int64_t *data = (int64_t *)addr;
803
804 return (dt_printf(dtp, fp, " %16lld", data[0] ?
805 (long long)(data[1] / (int64_t)normal / data[0]) : 0));
806 }
807
808 /*ARGSUSED*/
809 static int
810 dt_print_stddev(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr,
811 size_t size, uint64_t normal)
812 {
813 /* LINTED - alignment */
814 uint64_t *data = (uint64_t *)addr;
815
816 return (dt_printf(dtp, fp, " %16llu", data[0] ?
817 (unsigned long long) dt_stddev(data, normal) : 0));
818 }
819
820 /*ARGSUSED*/
821 int
822 dt_print_bytes(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr,
823 size_t nbytes, int width, int quiet, int forceraw)
824 {
825 /*
826 * If the byte stream is a series of printable characters, followed by
827 * a terminating byte, we print it out as a string. Otherwise, we
828 * assume that it's something else and just print the bytes.
829 */
830 int i, j, margin = 5;
831 char *c = (char *)addr;
832
833 if (nbytes == 0)
834 return (0);
835
836 if (forceraw)
837 goto raw;
838
839 if (dtp->dt_options[DTRACEOPT_RAWBYTES] != DTRACEOPT_UNSET)
840 goto raw;
841
854 c[i] == '\b' || c[i] == '\a')
855 continue;
856
857 if (c[i] == '\0' && i > 0) {
858 /*
859 * This looks like it might be a string. Before we
860 * assume that it is indeed a string, check the
861 * remainder of the byte range; if it contains
862 * additional non-nul characters, we'll assume that
863 * it's a binary stream that just happens to look like
864 * a string, and we'll print out the individual bytes.
865 */
866 for (j = i + 1; j < nbytes; j++) {
867 if (c[j] != '\0')
868 break;
869 }
870
871 if (j != nbytes)
872 break;
873
874 if (quiet)
875 return (dt_printf(dtp, fp, "%s", c));
876 else
877 return (dt_printf(dtp, fp, " %-*s", width, c));
878 }
879
880 break;
881 }
882
883 if (i == nbytes) {
884 /*
885 * The byte range is all printable characters, but there is
886 * no trailing nul byte. We'll assume that it's a string and
887 * print it as such.
888 */
889 char *s = alloca(nbytes + 1);
890 bcopy(c, s, nbytes);
891 s[nbytes] = '\0';
892 return (dt_printf(dtp, fp, " %-*s", width, s));
893 }
894
895 raw:
896 if (dt_printf(dtp, fp, "\n%*s ", margin, "") < 0)
897 return (-1);
1462 return (dt_set_errno(dtp, EDT_BADNORMAL));
1463 }
1464
1465 if (remaining < 0) {
1466 func = dtrace_aggregate_walk_valsorted;
1467 remaining = -remaining;
1468 } else {
1469 func = dtrace_aggregate_walk_valrevsorted;
1470 }
1471
1472 assert(remaining >= 0);
1473 trunc.dttd_remaining = remaining;
1474
1475 (void) func(dtp, dt_trunc_agg, &trunc);
1476
1477 return (0);
1478 }
1479
1480 static int
1481 dt_print_datum(dtrace_hdl_t *dtp, FILE *fp, dtrace_recdesc_t *rec,
1482 caddr_t addr, size_t size, uint64_t normal)
1483 {
1484 int err;
1485 dtrace_actkind_t act = rec->dtrd_action;
1486
1487 switch (act) {
1488 case DTRACEACT_STACK:
1489 return (dt_print_stack(dtp, fp, NULL, addr,
1490 rec->dtrd_arg, rec->dtrd_size / rec->dtrd_arg));
1491
1492 case DTRACEACT_USTACK:
1493 case DTRACEACT_JSTACK:
1494 return (dt_print_ustack(dtp, fp, NULL, addr, rec->dtrd_arg));
1495
1496 case DTRACEACT_USYM:
1497 case DTRACEACT_UADDR:
1498 return (dt_print_usym(dtp, fp, addr, act));
1499
1500 case DTRACEACT_UMOD:
1501 return (dt_print_umod(dtp, fp, NULL, addr));
1502
1503 case DTRACEACT_SYM:
1504 return (dt_print_sym(dtp, fp, NULL, addr));
1505
1508
1509 case DTRACEAGG_QUANTIZE:
1510 return (dt_print_quantize(dtp, fp, addr, size, normal));
1511
1512 case DTRACEAGG_LQUANTIZE:
1513 return (dt_print_lquantize(dtp, fp, addr, size, normal));
1514
1515 case DTRACEAGG_LLQUANTIZE:
1516 return (dt_print_llquantize(dtp, fp, addr, size, normal));
1517
1518 case DTRACEAGG_AVG:
1519 return (dt_print_average(dtp, fp, addr, size, normal));
1520
1521 case DTRACEAGG_STDDEV:
1522 return (dt_print_stddev(dtp, fp, addr, size, normal));
1523
1524 default:
1525 break;
1526 }
1527
1528 switch (size) {
1529 case sizeof (uint64_t):
1530 err = dt_printf(dtp, fp, " %16lld",
1531 /* LINTED - alignment */
1532 (long long)*((uint64_t *)addr) / normal);
1533 break;
1534 case sizeof (uint32_t):
1535 /* LINTED - alignment */
1536 err = dt_printf(dtp, fp, " %8d", *((uint32_t *)addr) /
1537 (uint32_t)normal);
1538 break;
1539 case sizeof (uint16_t):
1540 /* LINTED - alignment */
1541 err = dt_printf(dtp, fp, " %5d", *((uint16_t *)addr) /
1542 (uint32_t)normal);
1543 break;
1544 case sizeof (uint8_t):
1545 err = dt_printf(dtp, fp, " %3d", *((uint8_t *)addr) /
1546 (uint32_t)normal);
1547 break;
1548 default:
1549 err = dt_print_bytes(dtp, fp, addr, size, 50, 0, 0);
1550 break;
1551 }
1552
1553 return (err);
1554 }
1555
1556 int
1557 dt_print_aggs(const dtrace_aggdata_t **aggsdata, int naggvars, void *arg)
1558 {
1559 int i, aggact = 0;
1560 dt_print_aggdata_t *pd = arg;
1561 const dtrace_aggdata_t *aggdata = aggsdata[0];
1562 dtrace_aggdesc_t *agg = aggdata->dtada_desc;
1563 FILE *fp = pd->dtpa_fp;
1564 dtrace_hdl_t *dtp = pd->dtpa_dtp;
1565 dtrace_recdesc_t *rec;
1566 dtrace_actkind_t act;
1567 caddr_t addr;
1568 size_t size;
1569
1570 /*
1571 * Iterate over each record description in the key, printing the traced
1572 * data, skipping the first datum (the tuple member created by the
1573 * compiler).
1574 */
1575 for (i = 1; i < agg->dtagd_nrecs; i++) {
1576 rec = &agg->dtagd_rec[i];
1577 act = rec->dtrd_action;
1578 addr = aggdata->dtada_data + rec->dtrd_offset;
1579 size = rec->dtrd_size;
1580
1581 if (DTRACEACT_ISAGG(act)) {
1582 aggact = i;
1583 break;
1584 }
1585
1586 if (dt_print_datum(dtp, fp, rec, addr, size, 1) < 0)
1587 return (-1);
1588
1589 if (dt_buffered_flush(dtp, NULL, rec, aggdata,
1590 DTRACE_BUFDATA_AGGKEY) < 0)
1591 return (-1);
1592 }
1593
1594 assert(aggact != 0);
1595
1596 for (i = (naggvars == 1 ? 0 : 1); i < naggvars; i++) {
1597 uint64_t normal;
1598
1599 aggdata = aggsdata[i];
1600 agg = aggdata->dtada_desc;
1601 rec = &agg->dtagd_rec[aggact];
1602 act = rec->dtrd_action;
1603 addr = aggdata->dtada_data + rec->dtrd_offset;
1604 size = rec->dtrd_size;
1605
1606 assert(DTRACEACT_ISAGG(act));
1607 normal = aggdata->dtada_normal;
1608
1609 if (dt_print_datum(dtp, fp, rec, addr, size, normal) < 0)
1610 return (-1);
1611
1612 if (dt_buffered_flush(dtp, NULL, rec, aggdata,
1613 DTRACE_BUFDATA_AGGVAL) < 0)
1614 return (-1);
1615
1616 if (!pd->dtpa_allunprint)
1617 agg->dtagd_flags |= DTRACE_AGD_PRINTED;
1618 }
1619
1620 if (dt_printf(dtp, fp, "\n") < 0)
1621 return (-1);
1622
1623 if (dt_buffered_flush(dtp, NULL, NULL, aggdata,
1624 DTRACE_BUFDATA_AGGFORMAT | DTRACE_BUFDATA_AGGLAST) < 0)
1625 return (-1);
1626
1627 return (0);
1628 }
1629
1630 int
1631 dt_print_agg(const dtrace_aggdata_t *aggdata, void *arg)
1632 {
1633 dt_print_aggdata_t *pd = arg;
1634 dtrace_aggdesc_t *agg = aggdata->dtada_desc;
1635 dtrace_aggvarid_t aggvarid = pd->dtpa_id;
1636
1637 if (pd->dtpa_allunprint) {
1638 if (agg->dtagd_flags & DTRACE_AGD_PRINTED)
1639 return (0);
1640 } else {
1641 /*
2058 }
2059
2060 if (dt_printf(dtp, fp, "\n") < 0 ||
2061 dtrace_aggregate_walk_joined(dtp, aggvars,
2062 naggvars, dt_print_aggs, &pd) < 0) {
2063 dt_free(dtp, aggvars);
2064 return (-1);
2065 }
2066
2067 dt_free(dtp, aggvars);
2068 goto nextrec;
2069 }
2070
2071 if (act == DTRACEACT_TRACEMEM) {
2072 if (tracememsize == 0 ||
2073 tracememsize > rec->dtrd_size) {
2074 tracememsize = rec->dtrd_size;
2075 }
2076
2077 n = dt_print_bytes(dtp, fp, addr,
2078 tracememsize, 33, quiet, 1);
2079
2080 tracememsize = 0;
2081
2082 if (n < 0)
2083 return (-1);
2084
2085 goto nextrec;
2086 }
2087
2088 switch (rec->dtrd_size) {
2089 case sizeof (uint64_t):
2090 n = dt_printf(dtp, fp,
2091 quiet ? "%lld" : " %16lld",
2092 /* LINTED - alignment */
2093 *((unsigned long long *)addr));
2094 break;
2095 case sizeof (uint32_t):
2096 n = dt_printf(dtp, fp, quiet ? "%d" : " %8d",
2097 /* LINTED - alignment */
2098 *((uint32_t *)addr));
2099 break;
2100 case sizeof (uint16_t):
2101 n = dt_printf(dtp, fp, quiet ? "%d" : " %5d",
2102 /* LINTED - alignment */
2103 *((uint16_t *)addr));
2104 break;
2105 case sizeof (uint8_t):
2106 n = dt_printf(dtp, fp, quiet ? "%d" : " %3d",
2107 *((uint8_t *)addr));
2108 break;
2109 default:
2110 n = dt_print_bytes(dtp, fp, addr,
2111 rec->dtrd_size, 33, quiet, 0);
2112 break;
2113 }
2114
2115 if (n < 0)
2116 return (-1); /* errno is set for us */
2117
2118 nextrec:
2119 if (dt_buffered_flush(dtp, &data, rec, NULL, 0) < 0)
2120 return (-1); /* errno is set for us */
2121 }
2122
2123 /*
2124 * Call the record callback with a NULL record to indicate
2125 * that we're done processing this EPID.
2126 */
2127 rval = (*rfunc)(&data, NULL, arg);
2128 nextepid:
2129 offs += epd->dtepd_size;
2130 dtp->dt_last_epid = id;
2131 if (just_one) {
|
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /*
27 * Copyright (c) 2013, Joyent, Inc. All rights reserved.
28 * Copyright (c) 2012 by Delphix. All rights reserved.
29 */
30
31 #include <stdlib.h>
32 #include <strings.h>
33 #include <errno.h>
34 #include <unistd.h>
35 #include <limits.h>
36 #include <assert.h>
37 #include <ctype.h>
38 #include <alloca.h>
39 #include <dt_impl.h>
40 #include <dt_pq.h>
41
42 #define DT_MASK_LO 0x00000000FFFFFFFFULL
43
44 /*
45 * We declare this here because (1) we need it and (2) we want to avoid a
46 * dependency on libm in libdtrace.
47 */
48 static long double
49 dt_fabsl(long double x)
50 {
51 if (x < 0)
52 return (-x);
53
54 return (x);
55 }
56
57 static int
58 dt_ndigits(long long val)
59 {
60 int rval = 1;
61 long long cmp = 10;
62
63 if (val < 0) {
64 val = val == INT64_MIN ? INT64_MAX : -val;
65 rval++;
66 }
67
68 while (val > cmp && cmp > 0) {
69 rval++;
70 cmp *= 10;
71 }
72
73 return (rval < 4 ? 4 : rval);
74 }
75
76 /*
77 * 128-bit arithmetic functions needed to support the stddev() aggregating
78 * action.
79 */
80 static int
81 dt_gt_128(uint64_t *a, uint64_t *b)
82 {
83 return (a[1] > b[1] || (a[1] == b[1] && a[0] > b[0]));
84 }
85
86 static int
87 dt_ge_128(uint64_t *a, uint64_t *b)
88 {
89 return (a[1] > b[1] || (a[1] == b[1] && a[0] >= b[0]));
90 }
91
92 static int
93 dt_le_128(uint64_t *a, uint64_t *b)
94 {
95 return (a[1] < b[1] || (a[1] == b[1] && a[0] <= b[0]));
484 if (flow == DTRACEFLOW_RETURN && data->dtpda_indent > 0)
485 data->dtpda_indent -= 2;
486
487 data->dtpda_flow = flow;
488
489 return (0);
490 }
491
492 static int
493 dt_nullprobe()
494 {
495 return (DTRACE_CONSUME_THIS);
496 }
497
498 static int
499 dt_nullrec()
500 {
501 return (DTRACE_CONSUME_NEXT);
502 }
503
504 static void
505 dt_quantize_total(dtrace_hdl_t *dtp, int64_t datum, long double *total)
506 {
507 long double val = dt_fabsl((long double)datum);
508
509 if (dtp->dt_options[DTRACEOPT_AGGZOOM] == DTRACEOPT_UNSET) {
510 *total += val;
511 return;
512 }
513
514 /*
515 * If we're zooming in on an aggregation, we want the height of the
516 * highest value to be approximately 95% of total bar height -- so we
517 * adjust up by the reciprocal of DTRACE_AGGZOOM_MAX when comparing to
518 * our highest value.
519 */
520 val *= 1 / DTRACE_AGGZOOM_MAX;
521
522 if (*total < val)
523 *total = val;
524 }
525
526 static int
527 dt_print_quanthdr(dtrace_hdl_t *dtp, FILE *fp, int width)
528 {
529 return (dt_printf(dtp, fp, "\n%*s %41s %-9s\n",
530 width ? width : 16, width ? "key" : "value",
531 "------------- Distribution -------------", "count"));
532 }
533
534 static int
535 dt_print_quanthdr_packed(dtrace_hdl_t *dtp, FILE *fp, int width,
536 const dtrace_aggdata_t *aggdata, dtrace_actkind_t action)
537 {
538 int min = aggdata->dtada_minbin, max = aggdata->dtada_maxbin;
539 int minwidth, maxwidth, i;
540
541 assert(action == DTRACEAGG_QUANTIZE || action == DTRACEAGG_LQUANTIZE);
542
543 if (action == DTRACEAGG_QUANTIZE) {
544 if (min != 0 && min != DTRACE_QUANTIZE_ZEROBUCKET)
545 min--;
546
547 if (max < DTRACE_QUANTIZE_NBUCKETS - 1)
548 max++;
549
550 minwidth = dt_ndigits(DTRACE_QUANTIZE_BUCKETVAL(min));
551 maxwidth = dt_ndigits(DTRACE_QUANTIZE_BUCKETVAL(max));
552 } else {
553 maxwidth = 8;
554 minwidth = maxwidth - 1;
555 max++;
556 }
557
558 if (dt_printf(dtp, fp, "\n%*s %*s .",
559 width, width > 0 ? "key" : "", minwidth, "min") < 0)
560 return (-1);
561
562 for (i = min; i <= max; i++) {
563 if (dt_printf(dtp, fp, "-") < 0)
564 return (-1);
565 }
566
567 return (dt_printf(dtp, fp, ". %*s | count\n", -maxwidth, "max"));
568 }
569
570 /*
571 * We use a subset of the Unicode Block Elements (U+2588 through U+258F,
572 * inclusive) to represent aggregations via UTF-8 -- which are expressed via
573 * 3-byte UTF-8 sequences.
574 */
575 #define DTRACE_AGGUTF8_FULL 0x2588
576 #define DTRACE_AGGUTF8_BASE 0x258f
577 #define DTRACE_AGGUTF8_LEVELS 8
578
579 #define DTRACE_AGGUTF8_BYTE0(val) (0xe0 | ((val) >> 12))
580 #define DTRACE_AGGUTF8_BYTE1(val) (0x80 | (((val) >> 6) & 0x3f))
581 #define DTRACE_AGGUTF8_BYTE2(val) (0x80 | ((val) & 0x3f))
582
583 static int
584 dt_print_quantline_utf8(dtrace_hdl_t *dtp, FILE *fp, int64_t val,
585 uint64_t normal, long double total)
586 {
587 uint_t len = 40, i, whole, partial;
588 long double f = (dt_fabsl((long double)val) * len) / total;
589 const char *spaces = " ";
590
591 whole = (uint_t)f;
592 partial = (uint_t)((f - (long double)(uint_t)f) *
593 (long double)DTRACE_AGGUTF8_LEVELS);
594
595 if (dt_printf(dtp, fp, "|") < 0)
596 return (-1);
597
598 for (i = 0; i < whole; i++) {
599 if (dt_printf(dtp, fp, "%c%c%c",
600 DTRACE_AGGUTF8_BYTE0(DTRACE_AGGUTF8_FULL),
601 DTRACE_AGGUTF8_BYTE1(DTRACE_AGGUTF8_FULL),
602 DTRACE_AGGUTF8_BYTE2(DTRACE_AGGUTF8_FULL)) < 0)
603 return (-1);
604 }
605
606 if (partial != 0) {
607 partial = DTRACE_AGGUTF8_BASE - (partial - 1);
608
609 if (dt_printf(dtp, fp, "%c%c%c",
610 DTRACE_AGGUTF8_BYTE0(partial),
611 DTRACE_AGGUTF8_BYTE1(partial),
612 DTRACE_AGGUTF8_BYTE2(partial)) < 0)
613 return (-1);
614
615 i++;
616 }
617
618 return (dt_printf(dtp, fp, "%s %-9lld\n", spaces + i,
619 (long long)val / normal));
620 }
621
622 static int
623 dt_print_quantline(dtrace_hdl_t *dtp, FILE *fp, int64_t val,
624 uint64_t normal, long double total, char positives, char negatives)
625 {
626 long double f;
627 uint_t depth, len = 40;
628
629 const char *ats = "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@";
630 const char *spaces = " ";
631
632 assert(strlen(ats) == len && strlen(spaces) == len);
633 assert(!(total == 0 && (positives || negatives)));
634 assert(!(val < 0 && !negatives));
635 assert(!(val > 0 && !positives));
636 assert(!(val != 0 && total == 0));
637
638 if (!negatives) {
639 if (positives) {
640 if (dtp->dt_encoding == DT_ENCODING_UTF8) {
641 return (dt_print_quantline_utf8(dtp, fp, val,
642 normal, total));
643 }
644
645 f = (dt_fabsl((long double)val) * len) / total;
646 depth = (uint_t)(f + 0.5);
647 } else {
648 depth = 0;
649 }
650
651 return (dt_printf(dtp, fp, "|%s%s %-9lld\n", ats + len - depth,
652 spaces + depth, (long long)val / normal));
653 }
654
655 if (!positives) {
656 f = (dt_fabsl((long double)val) * len) / total;
657 depth = (uint_t)(f + 0.5);
658
659 return (dt_printf(dtp, fp, "%s%s| %-9lld\n", spaces + depth,
660 ats + len - depth, (long long)val / normal));
661 }
662
663 /*
664 * If we're here, we have both positive and negative bucket values.
667 * the size of normal quantize()/lquantize() bars, so we divide the
668 * length in half before calculating the bar length.
669 */
670 len /= 2;
671 ats = &ats[len];
672 spaces = &spaces[len];
673
674 f = (dt_fabsl((long double)val) * len) / total;
675 depth = (uint_t)(f + 0.5);
676
677 if (val <= 0) {
678 return (dt_printf(dtp, fp, "%s%s|%*s %-9lld\n", spaces + depth,
679 ats + len - depth, len, "", (long long)val / normal));
680 } else {
681 return (dt_printf(dtp, fp, "%20s|%s%s %-9lld\n", "",
682 ats + len - depth, spaces + depth,
683 (long long)val / normal));
684 }
685 }
686
687 /*
688 * As with UTF-8 printing of aggregations, we use a subset of the Unicode
689 * Block Elements (U+2581 through U+2588, inclusive) to represent our packed
690 * aggregation.
691 */
692 #define DTRACE_AGGPACK_BASE 0x2581
693 #define DTRACE_AGGPACK_LEVELS 8
694
695 static int
696 dt_print_packed(dtrace_hdl_t *dtp, FILE *fp,
697 long double datum, long double total)
698 {
699 static boolean_t utf8_checked = B_FALSE;
700 static boolean_t utf8;
701 char *ascii = "__xxxxXX";
702 char *neg = "vvvvVV";
703 unsigned int len;
704 long double val;
705
706 if (!utf8_checked) {
707 char *term;
708
709 /*
710 * We want to determine if we can reasonably emit UTF-8 for our
711 * packed aggregation. To do this, we will check for terminals
712 * that are known to be primitive to emit UTF-8 on these.
713 */
714 utf8_checked = B_TRUE;
715
716 if (dtp->dt_encoding == DT_ENCODING_ASCII)
717 utf8 = B_FALSE;
718 else if (dtp->dt_encoding == DT_ENCODING_UTF8)
719 utf8 = B_TRUE;
720 else if ((term = getenv("TERM")) != NULL &&
721 (strcmp(term, "sun") == 0 ||
722 strcmp(term, "sun-color") == 0) ||
723 strcmp(term, "dumb") == 0)
724 utf8 = B_FALSE;
725 else
726 utf8 = B_TRUE;
727 }
728
729 if (datum == 0)
730 return (dt_printf(dtp, fp, " "));
731
732 if (datum < 0) {
733 len = strlen(neg);
734 val = dt_fabsl(datum * (len - 1)) / total;
735 return (dt_printf(dtp, fp, "%c", neg[(uint_t)(val + 0.5)]));
736 }
737
738 if (utf8) {
739 int block = DTRACE_AGGPACK_BASE + (unsigned int)(((datum *
740 (DTRACE_AGGPACK_LEVELS - 1)) / total) + 0.5);
741
742 return (dt_printf(dtp, fp, "%c%c%c",
743 DTRACE_AGGUTF8_BYTE0(block),
744 DTRACE_AGGUTF8_BYTE1(block),
745 DTRACE_AGGUTF8_BYTE2(block)));
746 }
747
748 len = strlen(ascii);
749 val = (datum * (len - 1)) / total;
750 return (dt_printf(dtp, fp, "%c", ascii[(uint_t)(val + 0.5)]));
751 }
752
753 int
754 dt_print_quantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
755 size_t size, uint64_t normal)
756 {
757 const int64_t *data = addr;
758 int i, first_bin = 0, last_bin = DTRACE_QUANTIZE_NBUCKETS - 1;
759 long double total = 0;
760 char positives = 0, negatives = 0;
761
762 if (size != DTRACE_QUANTIZE_NBUCKETS * sizeof (uint64_t))
763 return (dt_set_errno(dtp, EDT_DMISMATCH));
764
765 while (first_bin < DTRACE_QUANTIZE_NBUCKETS - 1 && data[first_bin] == 0)
766 first_bin++;
767
768 if (first_bin == DTRACE_QUANTIZE_NBUCKETS - 1) {
769 /*
770 * There isn't any data. This is possible if the aggregation
771 * has been clear()'d or if negative increment values have been
772 * used. Regardless, we'll print the buckets around 0.
773 */
774 first_bin = DTRACE_QUANTIZE_ZEROBUCKET - 1;
775 last_bin = DTRACE_QUANTIZE_ZEROBUCKET + 1;
776 } else {
777 if (first_bin > 0)
778 first_bin--;
779
780 while (last_bin > 0 && data[last_bin] == 0)
781 last_bin--;
782
783 if (last_bin < DTRACE_QUANTIZE_NBUCKETS - 1)
784 last_bin++;
785 }
786
787 for (i = first_bin; i <= last_bin; i++) {
788 positives |= (data[i] > 0);
789 negatives |= (data[i] < 0);
790 dt_quantize_total(dtp, data[i], &total);
791 }
792
793 if (dt_print_quanthdr(dtp, fp, 0) < 0)
794 return (-1);
795
796 for (i = first_bin; i <= last_bin; i++) {
797 if (dt_printf(dtp, fp, "%16lld ",
798 (long long)DTRACE_QUANTIZE_BUCKETVAL(i)) < 0)
799 return (-1);
800
801 if (dt_print_quantline(dtp, fp, data[i], normal, total,
802 positives, negatives) < 0)
803 return (-1);
804 }
805
806 return (0);
807 }
808
809 int
810 dt_print_quantize_packed(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
811 size_t size, const dtrace_aggdata_t *aggdata)
812 {
813 const int64_t *data = addr;
814 long double total = 0, count = 0;
815 int min = aggdata->dtada_minbin, max = aggdata->dtada_maxbin, i;
816 int64_t minval, maxval;
817
818 if (size != DTRACE_QUANTIZE_NBUCKETS * sizeof (uint64_t))
819 return (dt_set_errno(dtp, EDT_DMISMATCH));
820
821 if (min != 0 && min != DTRACE_QUANTIZE_ZEROBUCKET)
822 min--;
823
824 if (max < DTRACE_QUANTIZE_NBUCKETS - 1)
825 max++;
826
827 minval = DTRACE_QUANTIZE_BUCKETVAL(min);
828 maxval = DTRACE_QUANTIZE_BUCKETVAL(max);
829
830 if (dt_printf(dtp, fp, " %*lld :", dt_ndigits(minval),
831 (long long)minval) < 0)
832 return (-1);
833
834 for (i = min; i <= max; i++) {
835 dt_quantize_total(dtp, data[i], &total);
836 count += data[i];
837 }
838
839 for (i = min; i <= max; i++) {
840 if (dt_print_packed(dtp, fp, data[i], total) < 0)
841 return (-1);
842 }
843
844 if (dt_printf(dtp, fp, ": %*lld | %lld\n",
845 -dt_ndigits(maxval), (long long)maxval, (long long)count) < 0)
846 return (-1);
847
848 return (0);
849 }
850
851 int
852 dt_print_lquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
853 size_t size, uint64_t normal)
854 {
855 const int64_t *data = addr;
856 int i, first_bin, last_bin, base;
857 uint64_t arg;
858 long double total = 0;
859 uint16_t step, levels;
860 char positives = 0, negatives = 0;
861
862 if (size < sizeof (uint64_t))
863 return (dt_set_errno(dtp, EDT_DMISMATCH));
864
865 arg = *data++;
866 size -= sizeof (uint64_t);
867
868 base = DTRACE_LQUANTIZE_BASE(arg);
869 step = DTRACE_LQUANTIZE_STEP(arg);
870 levels = DTRACE_LQUANTIZE_LEVELS(arg);
871
878 while (first_bin <= levels + 1 && data[first_bin] == 0)
879 first_bin++;
880
881 if (first_bin > levels + 1) {
882 first_bin = 0;
883 last_bin = 2;
884 } else {
885 if (first_bin > 0)
886 first_bin--;
887
888 while (last_bin > 0 && data[last_bin] == 0)
889 last_bin--;
890
891 if (last_bin < levels + 1)
892 last_bin++;
893 }
894
895 for (i = first_bin; i <= last_bin; i++) {
896 positives |= (data[i] > 0);
897 negatives |= (data[i] < 0);
898 dt_quantize_total(dtp, data[i], &total);
899 }
900
901 if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value",
902 "------------- Distribution -------------", "count") < 0)
903 return (-1);
904
905 for (i = first_bin; i <= last_bin; i++) {
906 char c[32];
907 int err;
908
909 if (i == 0) {
910 (void) snprintf(c, sizeof (c), "< %d", base);
911 err = dt_printf(dtp, fp, "%16s ", c);
912 } else if (i == levels + 1) {
913 (void) snprintf(c, sizeof (c), ">= %d",
914 base + (levels * step));
915 err = dt_printf(dtp, fp, "%16s ", c);
916 } else {
917 err = dt_printf(dtp, fp, "%16d ",
918 base + (i - 1) * step);
919 }
920
921 if (err < 0 || dt_print_quantline(dtp, fp, data[i], normal,
922 total, positives, negatives) < 0)
923 return (-1);
924 }
925
926 return (0);
927 }
928
929 /*ARGSUSED*/
930 int
931 dt_print_lquantize_packed(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
932 size_t size, const dtrace_aggdata_t *aggdata)
933 {
934 const int64_t *data = addr;
935 long double total = 0, count = 0;
936 int min, max, base, err;
937 uint64_t arg;
938 uint16_t step, levels;
939 char c[32];
940 unsigned int i;
941
942 if (size < sizeof (uint64_t))
943 return (dt_set_errno(dtp, EDT_DMISMATCH));
944
945 arg = *data++;
946 size -= sizeof (uint64_t);
947
948 base = DTRACE_LQUANTIZE_BASE(arg);
949 step = DTRACE_LQUANTIZE_STEP(arg);
950 levels = DTRACE_LQUANTIZE_LEVELS(arg);
951
952 if (size != sizeof (uint64_t) * (levels + 2))
953 return (dt_set_errno(dtp, EDT_DMISMATCH));
954
955 min = 0;
956 max = levels + 1;
957
958 if (min == 0) {
959 (void) snprintf(c, sizeof (c), "< %d", base);
960 err = dt_printf(dtp, fp, "%8s :", c);
961 } else {
962 err = dt_printf(dtp, fp, "%8d :", base + (min - 1) * step);
963 }
964
965 if (err < 0)
966 return (-1);
967
968 for (i = min; i <= max; i++) {
969 dt_quantize_total(dtp, data[i], &total);
970 count += data[i];
971 }
972
973 for (i = min; i <= max; i++) {
974 if (dt_print_packed(dtp, fp, data[i], total) < 0)
975 return (-1);
976 }
977
978 (void) snprintf(c, sizeof (c), ">= %d", base + (levels * step));
979 return (dt_printf(dtp, fp, ": %-8s | %lld\n", c, (long long)count));
980 }
981
982 int
983 dt_print_llquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
984 size_t size, uint64_t normal)
985 {
986 int i, first_bin, last_bin, bin = 1, order, levels;
987 uint16_t factor, low, high, nsteps;
988 const int64_t *data = addr;
989 int64_t value = 1, next, step;
990 char positives = 0, negatives = 0;
991 long double total = 0;
992 uint64_t arg;
993 char c[32];
994
995 if (size < sizeof (uint64_t))
996 return (dt_set_errno(dtp, EDT_DMISMATCH));
997
998 arg = *data++;
999 size -= sizeof (uint64_t);
1000
1001 factor = DTRACE_LLQUANTIZE_FACTOR(arg);
1019 while (first_bin < levels && data[first_bin] == 0)
1020 first_bin++;
1021
1022 if (first_bin == levels) {
1023 first_bin = 0;
1024 last_bin = 1;
1025 } else {
1026 if (first_bin > 0)
1027 first_bin--;
1028
1029 while (last_bin > 0 && data[last_bin] == 0)
1030 last_bin--;
1031
1032 if (last_bin < levels - 1)
1033 last_bin++;
1034 }
1035
1036 for (i = first_bin; i <= last_bin; i++) {
1037 positives |= (data[i] > 0);
1038 negatives |= (data[i] < 0);
1039 dt_quantize_total(dtp, data[i], &total);
1040 }
1041
1042 if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value",
1043 "------------- Distribution -------------", "count") < 0)
1044 return (-1);
1045
1046 for (order = 0; order < low; order++)
1047 value *= factor;
1048
1049 next = value * factor;
1050 step = next > nsteps ? next / nsteps : 1;
1051
1052 if (first_bin == 0) {
1053 (void) snprintf(c, sizeof (c), "< %lld", value);
1054
1055 if (dt_printf(dtp, fp, "%16s ", c) < 0)
1056 return (-1);
1057
1058 if (dt_print_quantline(dtp, fp, data[0], normal,
1059 total, positives, negatives) < 0)
1102 /* LINTED - alignment */
1103 int64_t *data = (int64_t *)addr;
1104
1105 return (dt_printf(dtp, fp, " %16lld", data[0] ?
1106 (long long)(data[1] / (int64_t)normal / data[0]) : 0));
1107 }
1108
1109 /*ARGSUSED*/
1110 static int
1111 dt_print_stddev(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr,
1112 size_t size, uint64_t normal)
1113 {
1114 /* LINTED - alignment */
1115 uint64_t *data = (uint64_t *)addr;
1116
1117 return (dt_printf(dtp, fp, " %16llu", data[0] ?
1118 (unsigned long long) dt_stddev(data, normal) : 0));
1119 }
1120
1121 /*ARGSUSED*/
1122 static int
1123 dt_print_bytes(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr,
1124 size_t nbytes, int width, int quiet, int forceraw)
1125 {
1126 /*
1127 * If the byte stream is a series of printable characters, followed by
1128 * a terminating byte, we print it out as a string. Otherwise, we
1129 * assume that it's something else and just print the bytes.
1130 */
1131 int i, j, margin = 5;
1132 char *c = (char *)addr;
1133
1134 if (nbytes == 0)
1135 return (0);
1136
1137 if (forceraw)
1138 goto raw;
1139
1140 if (dtp->dt_options[DTRACEOPT_RAWBYTES] != DTRACEOPT_UNSET)
1141 goto raw;
1142
1155 c[i] == '\b' || c[i] == '\a')
1156 continue;
1157
1158 if (c[i] == '\0' && i > 0) {
1159 /*
1160 * This looks like it might be a string. Before we
1161 * assume that it is indeed a string, check the
1162 * remainder of the byte range; if it contains
1163 * additional non-nul characters, we'll assume that
1164 * it's a binary stream that just happens to look like
1165 * a string, and we'll print out the individual bytes.
1166 */
1167 for (j = i + 1; j < nbytes; j++) {
1168 if (c[j] != '\0')
1169 break;
1170 }
1171
1172 if (j != nbytes)
1173 break;
1174
1175 if (quiet) {
1176 return (dt_printf(dtp, fp, "%s", c));
1177 } else {
1178 return (dt_printf(dtp, fp, " %s%*s",
1179 width < 0 ? " " : "", width, c));
1180 }
1181 }
1182
1183 break;
1184 }
1185
1186 if (i == nbytes) {
1187 /*
1188 * The byte range is all printable characters, but there is
1189 * no trailing nul byte. We'll assume that it's a string and
1190 * print it as such.
1191 */
1192 char *s = alloca(nbytes + 1);
1193 bcopy(c, s, nbytes);
1194 s[nbytes] = '\0';
1195 return (dt_printf(dtp, fp, " %-*s", width, s));
1196 }
1197
1198 raw:
1199 if (dt_printf(dtp, fp, "\n%*s ", margin, "") < 0)
1200 return (-1);
1765 return (dt_set_errno(dtp, EDT_BADNORMAL));
1766 }
1767
1768 if (remaining < 0) {
1769 func = dtrace_aggregate_walk_valsorted;
1770 remaining = -remaining;
1771 } else {
1772 func = dtrace_aggregate_walk_valrevsorted;
1773 }
1774
1775 assert(remaining >= 0);
1776 trunc.dttd_remaining = remaining;
1777
1778 (void) func(dtp, dt_trunc_agg, &trunc);
1779
1780 return (0);
1781 }
1782
1783 static int
1784 dt_print_datum(dtrace_hdl_t *dtp, FILE *fp, dtrace_recdesc_t *rec,
1785 caddr_t addr, size_t size, const dtrace_aggdata_t *aggdata,
1786 uint64_t normal, dt_print_aggdata_t *pd)
1787 {
1788 int err, width;
1789 dtrace_actkind_t act = rec->dtrd_action;
1790 boolean_t packed = pd->dtpa_agghist || pd->dtpa_aggpack;
1791 dtrace_aggdesc_t *agg = aggdata->dtada_desc;
1792
1793 static struct {
1794 size_t size;
1795 int width;
1796 int packedwidth;
1797 } *fmt, fmttab[] = {
1798 { sizeof (uint8_t), 3, 3 },
1799 { sizeof (uint16_t), 5, 5 },
1800 { sizeof (uint32_t), 8, 8 },
1801 { sizeof (uint64_t), 16, 16 },
1802 { 0, -50, 16 }
1803 };
1804
1805 if (packed && pd->dtpa_agghisthdr != agg->dtagd_varid) {
1806 dtrace_recdesc_t *r;
1807
1808 width = 0;
1809
1810 /*
1811 * To print our quantization header for either an agghist or
1812 * aggpack aggregation, we need to iterate through all of our
1813 * of our records to determine their width.
1814 */
1815 for (r = rec; !DTRACEACT_ISAGG(r->dtrd_action); r++) {
1816 for (fmt = fmttab; fmt->size &&
1817 fmt->size != r->dtrd_size; fmt++)
1818 continue;
1819
1820 width += fmt->packedwidth + 1;
1821 }
1822
1823 if (pd->dtpa_agghist) {
1824 if (dt_print_quanthdr(dtp, fp, width) < 0)
1825 return (-1);
1826 } else {
1827 if (dt_print_quanthdr_packed(dtp, fp,
1828 width, aggdata, r->dtrd_action) < 0)
1829 return (-1);
1830 }
1831
1832 pd->dtpa_agghisthdr = agg->dtagd_varid;
1833 }
1834
1835 if (pd->dtpa_agghist && DTRACEACT_ISAGG(act)) {
1836 char positives = aggdata->dtada_flags & DTRACE_A_HASPOSITIVES;
1837 char negatives = aggdata->dtada_flags & DTRACE_A_HASNEGATIVES;
1838 int64_t val;
1839
1840 assert(act == DTRACEAGG_SUM || act == DTRACEAGG_COUNT);
1841 val = (long long)*((uint64_t *)addr);
1842
1843 if (dt_printf(dtp, fp, " ") < 0)
1844 return (-1);
1845
1846 return (dt_print_quantline(dtp, fp, val, normal,
1847 aggdata->dtada_total, positives, negatives));
1848 }
1849
1850 if (pd->dtpa_aggpack && DTRACEACT_ISAGG(act)) {
1851 switch (act) {
1852 case DTRACEAGG_QUANTIZE:
1853 return (dt_print_quantize_packed(dtp,
1854 fp, addr, size, aggdata));
1855 case DTRACEAGG_LQUANTIZE:
1856 return (dt_print_lquantize_packed(dtp,
1857 fp, addr, size, aggdata));
1858 default:
1859 break;
1860 }
1861 }
1862
1863 switch (act) {
1864 case DTRACEACT_STACK:
1865 return (dt_print_stack(dtp, fp, NULL, addr,
1866 rec->dtrd_arg, rec->dtrd_size / rec->dtrd_arg));
1867
1868 case DTRACEACT_USTACK:
1869 case DTRACEACT_JSTACK:
1870 return (dt_print_ustack(dtp, fp, NULL, addr, rec->dtrd_arg));
1871
1872 case DTRACEACT_USYM:
1873 case DTRACEACT_UADDR:
1874 return (dt_print_usym(dtp, fp, addr, act));
1875
1876 case DTRACEACT_UMOD:
1877 return (dt_print_umod(dtp, fp, NULL, addr));
1878
1879 case DTRACEACT_SYM:
1880 return (dt_print_sym(dtp, fp, NULL, addr));
1881
1884
1885 case DTRACEAGG_QUANTIZE:
1886 return (dt_print_quantize(dtp, fp, addr, size, normal));
1887
1888 case DTRACEAGG_LQUANTIZE:
1889 return (dt_print_lquantize(dtp, fp, addr, size, normal));
1890
1891 case DTRACEAGG_LLQUANTIZE:
1892 return (dt_print_llquantize(dtp, fp, addr, size, normal));
1893
1894 case DTRACEAGG_AVG:
1895 return (dt_print_average(dtp, fp, addr, size, normal));
1896
1897 case DTRACEAGG_STDDEV:
1898 return (dt_print_stddev(dtp, fp, addr, size, normal));
1899
1900 default:
1901 break;
1902 }
1903
1904 for (fmt = fmttab; fmt->size && fmt->size != size; fmt++)
1905 continue;
1906
1907 width = packed ? fmt->packedwidth : fmt->width;
1908
1909 switch (size) {
1910 case sizeof (uint64_t):
1911 err = dt_printf(dtp, fp, " %*lld", width,
1912 /* LINTED - alignment */
1913 (long long)*((uint64_t *)addr) / normal);
1914 break;
1915 case sizeof (uint32_t):
1916 /* LINTED - alignment */
1917 err = dt_printf(dtp, fp, " %*d", width, *((uint32_t *)addr) /
1918 (uint32_t)normal);
1919 break;
1920 case sizeof (uint16_t):
1921 /* LINTED - alignment */
1922 err = dt_printf(dtp, fp, " %*d", width, *((uint16_t *)addr) /
1923 (uint32_t)normal);
1924 break;
1925 case sizeof (uint8_t):
1926 err = dt_printf(dtp, fp, " %*d", width, *((uint8_t *)addr) /
1927 (uint32_t)normal);
1928 break;
1929 default:
1930 err = dt_print_bytes(dtp, fp, addr, size, width, 0, 0);
1931 break;
1932 }
1933
1934 return (err);
1935 }
1936
1937 int
1938 dt_print_aggs(const dtrace_aggdata_t **aggsdata, int naggvars, void *arg)
1939 {
1940 int i, aggact = 0;
1941 dt_print_aggdata_t *pd = arg;
1942 const dtrace_aggdata_t *aggdata = aggsdata[0];
1943 dtrace_aggdesc_t *agg = aggdata->dtada_desc;
1944 FILE *fp = pd->dtpa_fp;
1945 dtrace_hdl_t *dtp = pd->dtpa_dtp;
1946 dtrace_recdesc_t *rec;
1947 dtrace_actkind_t act;
1948 caddr_t addr;
1949 size_t size;
1950
1951 pd->dtpa_agghist = (aggdata->dtada_flags & DTRACE_A_TOTAL);
1952 pd->dtpa_aggpack = (aggdata->dtada_flags & DTRACE_A_MINMAXBIN);
1953
1954 /*
1955 * Iterate over each record description in the key, printing the traced
1956 * data, skipping the first datum (the tuple member created by the
1957 * compiler).
1958 */
1959 for (i = 1; i < agg->dtagd_nrecs; i++) {
1960 rec = &agg->dtagd_rec[i];
1961 act = rec->dtrd_action;
1962 addr = aggdata->dtada_data + rec->dtrd_offset;
1963 size = rec->dtrd_size;
1964
1965 if (DTRACEACT_ISAGG(act)) {
1966 aggact = i;
1967 break;
1968 }
1969
1970 if (dt_print_datum(dtp, fp, rec, addr,
1971 size, aggdata, 1, pd) < 0)
1972 return (-1);
1973
1974 if (dt_buffered_flush(dtp, NULL, rec, aggdata,
1975 DTRACE_BUFDATA_AGGKEY) < 0)
1976 return (-1);
1977 }
1978
1979 assert(aggact != 0);
1980
1981 for (i = (naggvars == 1 ? 0 : 1); i < naggvars; i++) {
1982 uint64_t normal;
1983
1984 aggdata = aggsdata[i];
1985 agg = aggdata->dtada_desc;
1986 rec = &agg->dtagd_rec[aggact];
1987 act = rec->dtrd_action;
1988 addr = aggdata->dtada_data + rec->dtrd_offset;
1989 size = rec->dtrd_size;
1990
1991 assert(DTRACEACT_ISAGG(act));
1992 normal = aggdata->dtada_normal;
1993
1994 if (dt_print_datum(dtp, fp, rec, addr,
1995 size, aggdata, normal, pd) < 0)
1996 return (-1);
1997
1998 if (dt_buffered_flush(dtp, NULL, rec, aggdata,
1999 DTRACE_BUFDATA_AGGVAL) < 0)
2000 return (-1);
2001
2002 if (!pd->dtpa_allunprint)
2003 agg->dtagd_flags |= DTRACE_AGD_PRINTED;
2004 }
2005
2006 if (!pd->dtpa_agghist && !pd->dtpa_aggpack) {
2007 if (dt_printf(dtp, fp, "\n") < 0)
2008 return (-1);
2009 }
2010
2011 if (dt_buffered_flush(dtp, NULL, NULL, aggdata,
2012 DTRACE_BUFDATA_AGGFORMAT | DTRACE_BUFDATA_AGGLAST) < 0)
2013 return (-1);
2014
2015 return (0);
2016 }
2017
2018 int
2019 dt_print_agg(const dtrace_aggdata_t *aggdata, void *arg)
2020 {
2021 dt_print_aggdata_t *pd = arg;
2022 dtrace_aggdesc_t *agg = aggdata->dtada_desc;
2023 dtrace_aggvarid_t aggvarid = pd->dtpa_id;
2024
2025 if (pd->dtpa_allunprint) {
2026 if (agg->dtagd_flags & DTRACE_AGD_PRINTED)
2027 return (0);
2028 } else {
2029 /*
2446 }
2447
2448 if (dt_printf(dtp, fp, "\n") < 0 ||
2449 dtrace_aggregate_walk_joined(dtp, aggvars,
2450 naggvars, dt_print_aggs, &pd) < 0) {
2451 dt_free(dtp, aggvars);
2452 return (-1);
2453 }
2454
2455 dt_free(dtp, aggvars);
2456 goto nextrec;
2457 }
2458
2459 if (act == DTRACEACT_TRACEMEM) {
2460 if (tracememsize == 0 ||
2461 tracememsize > rec->dtrd_size) {
2462 tracememsize = rec->dtrd_size;
2463 }
2464
2465 n = dt_print_bytes(dtp, fp, addr,
2466 tracememsize, -33, quiet, 1);
2467
2468 tracememsize = 0;
2469
2470 if (n < 0)
2471 return (-1);
2472
2473 goto nextrec;
2474 }
2475
2476 switch (rec->dtrd_size) {
2477 case sizeof (uint64_t):
2478 n = dt_printf(dtp, fp,
2479 quiet ? "%lld" : " %16lld",
2480 /* LINTED - alignment */
2481 *((unsigned long long *)addr));
2482 break;
2483 case sizeof (uint32_t):
2484 n = dt_printf(dtp, fp, quiet ? "%d" : " %8d",
2485 /* LINTED - alignment */
2486 *((uint32_t *)addr));
2487 break;
2488 case sizeof (uint16_t):
2489 n = dt_printf(dtp, fp, quiet ? "%d" : " %5d",
2490 /* LINTED - alignment */
2491 *((uint16_t *)addr));
2492 break;
2493 case sizeof (uint8_t):
2494 n = dt_printf(dtp, fp, quiet ? "%d" : " %3d",
2495 *((uint8_t *)addr));
2496 break;
2497 default:
2498 n = dt_print_bytes(dtp, fp, addr,
2499 rec->dtrd_size, -33, quiet, 0);
2500 break;
2501 }
2502
2503 if (n < 0)
2504 return (-1); /* errno is set for us */
2505
2506 nextrec:
2507 if (dt_buffered_flush(dtp, &data, rec, NULL, 0) < 0)
2508 return (-1); /* errno is set for us */
2509 }
2510
2511 /*
2512 * Call the record callback with a NULL record to indicate
2513 * that we're done processing this EPID.
2514 */
2515 rval = (*rfunc)(&data, NULL, arg);
2516 nextepid:
2517 offs += epd->dtepd_size;
2518 dtp->dt_last_epid = id;
2519 if (just_one) {
|