diff options
author | Dan McDonald <danmcd@mnx.io> | 2022-11-10 11:06:38 -0500 |
---|---|---|
committer | Dan McDonald <danmcd@mnx.io> | 2022-11-10 11:06:38 -0500 |
commit | fe2789d05c8a7f2b216028f4b925f14ad6490f7e (patch) | |
tree | 2f6170d853de053c2c872d435b6496719a99b2d5 /usr/src/lib | |
parent | 758597efca5a7022fe4ed7c3b6653ed0068e795e (diff) | |
parent | 6eeafb34dceabceff80ed689002b6dc3e060f498 (diff) | |
download | illumos-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.c | 15 | ||||
-rw-r--r-- | usr/src/lib/libdtrace/common/dt_ident.c | 2 | ||||
-rw-r--r-- | usr/src/lib/libdtrace/common/dt_impl.h | 5 | ||||
-rw-r--r-- | usr/src/lib/libdtrace/common/dt_parser.c | 36 | ||||
-rw-r--r-- | usr/src/lib/libdtrace/common/dt_parser.h | 4 | ||||
-rw-r--r-- | usr/src/lib/libdtrace/common/dt_print.c | 43 | ||||
-rw-r--r-- | usr/src/lib/libdtrace/common/dt_subr.c | 23 | ||||
-rw-r--r-- | usr/src/lib/libdtrace/common/ip.d.in | 4 |
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>" : |