summaryrefslogtreecommitdiff
path: root/usr/src/lib
diff options
context:
space:
mode:
authorDan McDonald <danmcd@mnx.io>2022-11-10 11:06:38 -0500
committerDan McDonald <danmcd@mnx.io>2022-11-10 11:06:38 -0500
commitfe2789d05c8a7f2b216028f4b925f14ad6490f7e (patch)
tree2f6170d853de053c2c872d435b6496719a99b2d5 /usr/src/lib
parent758597efca5a7022fe4ed7c3b6653ed0068e795e (diff)
parent6eeafb34dceabceff80ed689002b6dc3e060f498 (diff)
downloadillumos-joyent-fe2789d05c8a7f2b216028f4b925f14ad6490f7e.tar.gz
[illumos-gate merge]
commit 6eeafb34dceabceff80ed689002b6dc3e060f498 15109 dtrace replicated mdb's bitfield mistakes 15111 dtrace -xtree doesn't always escape strings commit 603778843038dfbc5672c2565d9ce3dac034609d 15110 mdb ::printf replicated mdb ::print bitfield mistakes commit f651720770e11ade275c4fc451e6b00c9e5d3068 15126 ipv4info_t translator produces bad flags value 15113 dtrace ICMPv4 tests fail due to flags mismatch commit 17425aa5357a01155862de9af35ff553bab2bb86 15121 tst.temporal.ksh has PATH dependencies
Diffstat (limited to 'usr/src/lib')
-rw-r--r--usr/src/lib/libdtrace/common/dt_cg.c15
-rw-r--r--usr/src/lib/libdtrace/common/dt_ident.c2
-rw-r--r--usr/src/lib/libdtrace/common/dt_impl.h5
-rw-r--r--usr/src/lib/libdtrace/common/dt_parser.c36
-rw-r--r--usr/src/lib/libdtrace/common/dt_parser.h4
-rw-r--r--usr/src/lib/libdtrace/common/dt_print.c43
-rw-r--r--usr/src/lib/libdtrace/common/dt_subr.c23
-rw-r--r--usr/src/lib/libdtrace/common/ip.d.in4
8 files changed, 101 insertions, 31 deletions
diff --git a/usr/src/lib/libdtrace/common/dt_cg.c b/usr/src/lib/libdtrace/common/dt_cg.c
index 9f3625e6ee..816b31daf7 100644
--- a/usr/src/lib/libdtrace/common/dt_cg.c
+++ b/usr/src/lib/libdtrace/common/dt_cg.c
@@ -28,6 +28,7 @@
/*
* Copyright (c) 2012 by Delphix. All rights reserved.
* Copyright 2017 Joyent, Inc.
+ * Copyright 2022 Oxide Computer Company
*/
#include <sys/types.h>
@@ -160,15 +161,17 @@ dt_cg_load(dt_node_t *dnp, ctf_file_t *ctfp, ctf_id_t type)
ssize_t size;
/*
- * If we're loading a bit-field, the size of our load is found by
- * rounding cte_bits up to a byte boundary and then finding the
- * nearest power of two to this value (see clp2(), above).
+ * If we're loading a bit-field, we find the power-of-two that spans the
+ * full value. To do this we count the number of bytes that contain a
+ * portion of the bit-field.
*/
if ((dnp->dn_flags & DT_NF_BITFIELD) &&
- ctf_type_encoding(ctfp, type, &e) != CTF_ERR)
- size = clp2(P2ROUNDUP(e.cte_bits, NBBY) / NBBY);
- else
+ ctf_type_encoding(ctfp, type, &e) != CTF_ERR) {
+ uint_t nbits = e.cte_bits + (dnp->dn_bitoff % NBBY);
+ size = clp2(P2ROUNDUP(nbits, NBBY) / NBBY);
+ } else {
size = ctf_type_size(ctfp, type);
+ }
if (size < 1 || size > 8 || (size & (size - 1)) != 0) {
xyerror(D_UNKNOWN, "internal error -- cg cannot load "
diff --git a/usr/src/lib/libdtrace/common/dt_ident.c b/usr/src/lib/libdtrace/common/dt_ident.c
index 33f94eb9fd..6927132ada 100644
--- a/usr/src/lib/libdtrace/common/dt_ident.c
+++ b/usr/src/lib/libdtrace/common/dt_ident.c
@@ -23,6 +23,7 @@
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
* Copyright (c) 2013 Joyent, Inc. All rights reserved.
+ * Copyright 2022 Oxide Computer Company
*/
#include <sys/sysmacros.h>
@@ -266,6 +267,7 @@ dt_idcook_func(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *args)
if (strcmp(p1, "@") == 0 || strcmp(p1, "...") == 0) {
isp->dis_args[i].dn_ctfp = NULL;
isp->dis_args[i].dn_type = CTF_ERR;
+ isp->dis_args[i].dn_bitoff = 0;
if (*p1 == '.')
isp->dis_varargs = i;
continue;
diff --git a/usr/src/lib/libdtrace/common/dt_impl.h b/usr/src/lib/libdtrace/common/dt_impl.h
index 988b7f6fb7..cdf70586b0 100644
--- a/usr/src/lib/libdtrace/common/dt_impl.h
+++ b/usr/src/lib/libdtrace/common/dt_impl.h
@@ -27,6 +27,7 @@
/*
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
* Copyright (c) 2011, 2016 by Delphix. All rights reserved.
+ * Copyright 2022 Oxide Computer Company
*/
#ifndef _DT_IMPL_H
@@ -166,7 +167,7 @@ typedef struct dt_ahash {
} dt_ahash_t;
typedef struct dt_aggregate {
- dtrace_bufdesc_t dtat_buf; /* buf aggregation snapshot */
+ dtrace_bufdesc_t dtat_buf; /* buf aggregation snapshot */
int dtat_flags; /* aggregate flags */
processorid_t dtat_ncpus; /* number of CPUs in aggregate */
processorid_t *dtat_cpus; /* CPUs in aggregate */
@@ -653,6 +654,8 @@ extern int dt_handle_setopt(dtrace_hdl_t *, dtrace_setoptdata_t *);
extern int dt_lib_depend_add(dtrace_hdl_t *, dt_list_t *, const char *);
extern dt_lib_depend_t *dt_lib_depend_lookup(dt_list_t *, const char *);
+extern boolean_t dt_is_bitfield(const ctf_encoding_t *, ulong_t);
+
extern dt_pcb_t *yypcb; /* pointer to current parser control block */
extern char yyintprefix; /* int token prefix for macros (+/-) */
extern char yyintsuffix[4]; /* int token suffix ([uUlL]*) */
diff --git a/usr/src/lib/libdtrace/common/dt_parser.c b/usr/src/lib/libdtrace/common/dt_parser.c
index 176d9b7d48..9cd9520f0f 100644
--- a/usr/src/lib/libdtrace/common/dt_parser.c
+++ b/usr/src/lib/libdtrace/common/dt_parser.c
@@ -23,6 +23,7 @@
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, Joyent Inc. All rights reserved.
* Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+ * Copyright 2022 Oxide Computer Company
*/
/*
@@ -517,6 +518,7 @@ dt_node_xalloc(dtrace_hdl_t *dtp, int kind)
dnp->dn_ctfp = NULL;
dnp->dn_type = CTF_ERR;
+ dnp->dn_bitoff = 0;
dnp->dn_kind = (uchar_t)kind;
dnp->dn_flags = 0;
dnp->dn_op = 0;
@@ -671,8 +673,8 @@ dt_node_attr_assign(dt_node_t *dnp, dtrace_attribute_t attr)
}
void
-dt_node_type_assign(dt_node_t *dnp, ctf_file_t *fp, ctf_id_t type,
- boolean_t user)
+dt_node_type_assign_member(dt_node_t *dnp, ctf_file_t *fp, ctf_id_t type,
+ boolean_t user, ulong_t bitoff)
{
ctf_id_t base = ctf_type_resolve(fp, type);
uint_t kind = ctf_type_kind(fp, base);
@@ -682,9 +684,7 @@ dt_node_type_assign(dt_node_t *dnp, ctf_file_t *fp, ctf_id_t type,
~(DT_NF_SIGNED | DT_NF_REF | DT_NF_BITFIELD | DT_NF_USERLAND);
if (kind == CTF_K_INTEGER && ctf_type_encoding(fp, base, &e) == 0) {
- size_t size = e.cte_bits / NBBY;
-
- if (size > 8 || (e.cte_bits % NBBY) != 0 || (size & (size - 1)))
+ if (dt_is_bitfield(&e, bitoff))
dnp->dn_flags |= DT_NF_BITFIELD;
if (e.cte_format & CTF_INT_SIGNED)
@@ -710,6 +710,15 @@ dt_node_type_assign(dt_node_t *dnp, ctf_file_t *fp, ctf_id_t type,
dnp->dn_flags |= DT_NF_COOKED;
dnp->dn_ctfp = fp;
dnp->dn_type = type;
+ dnp->dn_bitoff = bitoff;
+}
+
+
+void
+dt_node_type_assign(dt_node_t *dnp, ctf_file_t *fp, ctf_id_t type,
+ boolean_t user)
+{
+ return (dt_node_type_assign_member(dnp, fp, type, user, 0));
}
void
@@ -719,6 +728,7 @@ dt_node_type_propagate(const dt_node_t *src, dt_node_t *dst)
dst->dn_flags = src->dn_flags & ~DT_NF_LVALUE;
dst->dn_ctfp = src->dn_ctfp;
dst->dn_type = src->dn_type;
+ dst->dn_bitoff = src->dn_bitoff;
}
const char *
@@ -1369,7 +1379,8 @@ dt_node_type(dt_decl_t *ddp)
dnp->dn_op = DT_TOK_IDENT;
dnp->dn_string = name;
- dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type, dtt.dtt_flags);
+ dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type,
+ (dtt.dtt_flags & DTT_FL_USER) != 0);
if (dtt.dtt_ctfp == dtp->dt_cdefs->dm_ctfp ||
dtt.dtt_ctfp == dtp->dt_ddefs->dm_ctfp)
@@ -1392,6 +1403,7 @@ dt_node_vatype(void)
dnp->dn_op = DT_TOK_IDENT;
dnp->dn_ctfp = yypcb->pcb_hdl->dt_cdefs->dm_ctfp;
dnp->dn_type = CTF_ERR;
+ dnp->dn_bitoff = 0;
dnp->dn_attr = _dtrace_defattr;
return (dnp);
@@ -3767,7 +3779,8 @@ asgn_common:
type = ctf_type_resolve(ctfp, m.ctm_type);
kind = ctf_type_kind(ctfp, type);
- dt_node_type_assign(dnp, ctfp, m.ctm_type, B_FALSE);
+ dt_node_type_assign_member(dnp, ctfp, m.ctm_type, B_FALSE,
+ m.ctm_offset);
dt_node_attr_assign(dnp, lp->dn_attr);
if (op == DT_TOK_PTR && (kind != CTF_K_ARRAY ||
@@ -4137,7 +4150,7 @@ dt_cook_aggregation(dt_node_t *dnp, uint_t idflags)
* probe-description-list
* /x++ && y == 0/
* {
- * trace(x + y++);
+ * trace(x + y++);
* }
*
* but it doesn't seem worth the complexity to handle such rare cases. The
@@ -4842,9 +4855,12 @@ dt_node_printr(dt_node_t *dnp, FILE *fp, int depth)
(u_longlong_t)dnp->dn_value, buf);
break;
- case DT_NODE_STRING:
- (void) fprintf(fp, "STRING \"%s\" (%s)\n", dnp->dn_string, buf);
+ case DT_NODE_STRING: {
+ char *escd = strchr2esc(dnp->dn_string, strlen(dnp->dn_string));
+ (void) fprintf(fp, "STRING \"%s\" (%s)\n", escd, buf);
+ free(escd);
break;
+ }
case DT_NODE_IDENT:
(void) fprintf(fp, "IDENT %s (%s)\n", dnp->dn_string, buf);
diff --git a/usr/src/lib/libdtrace/common/dt_parser.h b/usr/src/lib/libdtrace/common/dt_parser.h
index f5f60a518e..96022ac5c1 100644
--- a/usr/src/lib/libdtrace/common/dt_parser.h
+++ b/usr/src/lib/libdtrace/common/dt_parser.h
@@ -25,6 +25,7 @@
/*
* Copyright (c) 2013, 2016 by Delphix. All rights reserved.
* Copyright (c) 2013 Joyent, Inc. All rights reserved.
+ * Copyright 2022 Oxide Computer Company
*/
#ifndef _DT_PARSER_H
@@ -50,6 +51,7 @@ extern "C" {
typedef struct dt_node {
ctf_file_t *dn_ctfp; /* CTF type container for node's type */
ctf_id_t dn_type; /* CTF type reference for node's type */
+ ulong_t dn_bitoff; /* Offset to the start of the CTF type */
uchar_t dn_kind; /* node kind (DT_NODE_*, defined below) */
uchar_t dn_flags; /* node flags (DT_NF_*, defined below) */
ushort_t dn_op; /* operator (DT_TOK_*, defined by lex) */
@@ -239,6 +241,8 @@ extern void dt_node_link_free(dt_node_t **);
extern void dt_node_attr_assign(dt_node_t *, dtrace_attribute_t);
extern void dt_node_type_assign(dt_node_t *, ctf_file_t *, ctf_id_t, boolean_t);
+extern void dt_node_type_assign_bitfield(dt_node_t *, ctf_file_t *, ctf_id_t,
+ boolean_t, ulong_t);
extern void dt_node_type_propagate(const dt_node_t *, dt_node_t *);
extern const char *dt_node_type_name(const dt_node_t *, char *, size_t);
extern size_t dt_node_type_size(const dt_node_t *);
diff --git a/usr/src/lib/libdtrace/common/dt_print.c b/usr/src/lib/libdtrace/common/dt_print.c
index b71eddbf9d..4b4a23b199 100644
--- a/usr/src/lib/libdtrace/common/dt_print.c
+++ b/usr/src/lib/libdtrace/common/dt_print.c
@@ -27,6 +27,7 @@
*/
/*
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright 2022 Oxide Computer Company
*/
/*
@@ -41,13 +42,13 @@
*
* This implementation differs from MDB's in the following ways:
*
- * - We do not expose any options or flags. The behavior of print() is
+ * - We do not expose any options or flags. The behavior of print() is
* equivalent to "::print -tn".
*
- * - MDB will display "holes" in structures (unused padding between
+ * - MDB will display "holes" in structures (unused padding between
* members).
*
- * - When printing arrays of structures, MDB will leave a trailing ','
+ * - When printing arrays of structures, MDB will leave a trailing ','
* after the last element.
*
* - MDB will print time_t types as date and time.
@@ -149,7 +150,8 @@ dt_print_indent(dt_printarg_t *pap)
* Print a bitfield. It's worth noting that the D compiler support for
* bitfields is currently broken; printing "D`user_desc_t" (pulled in by the
* various D provider files) will produce incorrect results compared to
- * "genunix`user_desc_t".
+ * "genunix`user_desc_t". However, bitfields that are built via CTF will be
+ * fine. Note, this is derived from mdb's print_bifield in mdb_print.c.
*/
static void
print_bitfield(dt_printarg_t *pap, ulong_t off, ctf_encoding_t *ep)
@@ -158,11 +160,32 @@ print_bitfield(dt_printarg_t *pap, ulong_t off, ctf_encoding_t *ep)
caddr_t addr = pap->pa_addr + off / NBBY;
uint64_t mask = (1ULL << ep->cte_bits) - 1;
uint64_t value = 0;
- size_t size = (ep->cte_bits + (NBBY - 1)) / NBBY;
uint8_t *buf = (uint8_t *)&value;
uint8_t shift;
/*
+ * Our bitfield may straddle a byte boundary. We explicitly take the
+ * offset of the bitfield within its byte into account when determining
+ * the overall amount of data to copy and mask off from the underlying
+ * data.
+ */
+ uint_t nbits = ep->cte_bits + (off % NBBY);
+ size_t size = P2ROUNDUP(nbits, NBBY) / NBBY;
+
+ /*
+ * The resulting size must fit within the 64-bit value that we're using
+ * to store the value, otherwise the bcopy below could destroy our
+ * stack. This could be handled, but is not practically worth
+ * addressing. This choice apes mdb, so if you're considering fixing
+ * this, fix mdb as well.
+ */
+ if (size > sizeof (value)) {
+ (void) fprintf(fp, "??? (total bitfield too large after "
+ "alignment");
+ return;
+ }
+
+ /*
* On big-endian machines, we need to adjust the buf pointer to refer
* to the lowest 'size' bytes in 'value', and we need to shift based on
* the offset from the end of the data, not the offset of the start.
@@ -248,12 +271,8 @@ dt_print_int(ctf_id_t base, ulong_t off, dt_printarg_t *pap)
return;
}
- /*
- * We print this as a bitfield if the bit encoding indicates it's not
- * an even power of two byte size, or is larger than 8 bytes.
- */
size = e.cte_bits / NBBY;
- if (size > 8 || (e.cte_bits % NBBY) != 0 || (size & (size - 1)) != 0) {
+ if (dt_is_bitfield(&e, off)) {
print_bitfield(pap, off, &e);
return;
}
@@ -341,7 +360,7 @@ dt_print_ptr(ctf_id_t base, ulong_t off, dt_printarg_t *pap)
* each member, and recursively invoke ctf_type_visit() for each member. If
* the members are non-structs, then we print them out directly:
*
- * [ 0x14, 0x2e, 0 ]
+ * [ 0x14, 0x2e, 0 ]
*
* If they are structs, then we print out the necessary leading and trailing
* braces, to end up with:
@@ -408,7 +427,7 @@ dt_print_array(ctf_id_t base, ulong_t off, dt_printarg_t *pap)
* don't bother printing out the brackets. This lets print("foo") look
* like:
*
- * string "foo"
+ * string "foo"
*
* As D will internally represent this as a char[256] array.
*/
diff --git a/usr/src/lib/libdtrace/common/dt_subr.c b/usr/src/lib/libdtrace/common/dt_subr.c
index e93617ef59..1958e62f82 100644
--- a/usr/src/lib/libdtrace/common/dt_subr.c
+++ b/usr/src/lib/libdtrace/common/dt_subr.c
@@ -22,6 +22,7 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright 2022 Oxide Computer Company
*/
#include <sys/sysmacros.h>
@@ -909,3 +910,25 @@ dtrace_uaddr2str(dtrace_hdl_t *dtp, pid_t pid,
return (dt_string2str(c, str, nbytes));
}
+
+/*
+ * This is a shared implementation to determine if we should treat a type as a
+ * bitfield. The parameters are the CTF encoding and the bit offset of the
+ * integer. This also exists in mdb_print.c. We consider something a bitfield
+ * if:
+ *
+ * o The type is more than 8 bytes. This is a bit of a historical choice from
+ * mdb and is a stranger one. The normal integer handling code generally
+ * doesn't handle integers more than 64-bits in size. Of course neither does
+ * the bitfield code...
+ * o The bit count is not a multiple of 8.
+ * o The size in bytes is not a power of 2.
+ * o The offset is not a multiple of 8.
+ */
+boolean_t
+dt_is_bitfield(const ctf_encoding_t *ep, ulong_t off)
+{
+ size_t bsize = ep->cte_bits / NBBY;
+ return (bsize > 8 || (ep->cte_bits % NBBY) != 0 ||
+ (bsize & (bsize - 1)) != 0 || (off % NBBY) != 0);
+}
diff --git a/usr/src/lib/libdtrace/common/ip.d.in b/usr/src/lib/libdtrace/common/ip.d.in
index f1e6332529..7dd4d2a314 100644
--- a/usr/src/lib/libdtrace/common/ip.d.in
+++ b/usr/src/lib/libdtrace/common/ip.d.in
@@ -311,9 +311,9 @@ translator ipv4info_t < ipha_t *I > {
ipv4_length = I != NULL ? ntohs(I->ipha_length) : 0;
ipv4_ident = I != NULL ? ntohs(I->ipha_ident) : 0;
ipv4_flags = I != NULL ? ntohs(I->ipha_fragment_offset_and_flags) >>
- 12 : 0;
+ 13 : 0;
ipv4_offset = I != NULL ? ntohs(I->ipha_fragment_offset_and_flags) &
- 0x0fff : 0;
+ 0x1fff : 0;
ipv4_ttl = I != NULL ? I->ipha_ttl : 0;
ipv4_protocol = I != NULL ? I->ipha_protocol : 0;
ipv4_protostr = I == NULL ? "<null>" :