diff options
author | Robert Mustacchi <rm@fingolfin.org> | 2022-10-22 18:22:05 +0000 |
---|---|---|
committer | Robert Mustacchi <rm@fingolfin.org> | 2022-11-10 04:12:39 +0000 |
commit | 6eeafb34dceabceff80ed689002b6dc3e060f498 (patch) | |
tree | fe7289898a2a9c5fb349b5cd4d5aef9cfc5ea29a | |
parent | 603778843038dfbc5672c2565d9ce3dac034609d (diff) | |
download | illumos-gate-6eeafb34dceabceff80ed689002b6dc3e060f498.tar.gz |
15109 dtrace replicated mdb's bitfield mistakes
15111 dtrace -xtree doesn't always escape strings
Reviewed by: Adam Leventhal <adam.leventhal@gmail.com>
Approved by: Gordon Ross <gordon.w.ross@gmail.com>
-rw-r--r-- | usr/src/cmd/dtrace/test/tst/common/Makefile | 10 | ||||
-rw-r--r-- | usr/src/cmd/dtrace/test/tst/common/bitfields/tst.bitfields.c | 92 | ||||
-rw-r--r-- | usr/src/cmd/dtrace/test/tst/common/bitfields/tst.bitfields.ksh | 63 | ||||
-rw-r--r-- | usr/src/cmd/dtrace/test/tst/common/bitfields/tst.bitfields.ksh.out | 28 | ||||
-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/pkg/manifests/system-dtrace-tests.p5m | 3 |
12 files changed, 294 insertions, 30 deletions
diff --git a/usr/src/cmd/dtrace/test/tst/common/Makefile b/usr/src/cmd/dtrace/test/tst/common/Makefile index a29d774069..6237963c0e 100644 --- a/usr/src/cmd/dtrace/test/tst/common/Makefile +++ b/usr/src/cmd/dtrace/test/tst/common/Makefile @@ -28,6 +28,7 @@ # Copyright (c) 2012 by Delphix. All rights reserved. # Copyright 2015 Nexenta Systems, Inc. All rights reserved. # Copyright 2018 Joyent, Inc. +# Copyright 2022 Oxide Computer Company # # @@ -90,9 +91,16 @@ json/tst.usdt.exe: json/tst.usdt.o json/usdt.o $(POST_PROCESS) ; $(STRIP_STABS) # -# Tests that use the next three programs rely on the binaries having +# Tests that use the next four programs rely on the binaries having # valid CTF data. # +bitfields/tst.bitfields.exe: bitfields/tst.bitfields.c + $(COMPILE.c) $(CTF_FLAGS) -o bitfields/tst.bitfields.o bitfields/tst.bitfields.c + $(CTFCONVERT) -i -L VERSION bitfields/tst.bitfields.o + $(LINK.c) -o bitfields/tst.bitfields.exe bitfields/tst.bitfields.o $(LDLIBS) + $(CTFMERGE) -L VERSION -o $@ bitfields/tst.bitfields.o + $(POST_PROCESS) ; $(STRIP_STABS) + uctf/tst.aouttype.exe: uctf/tst.aouttype.c $(COMPILE.c) $(CTF_FLAGS) -o uctf/tst.aouttype.o uctf/tst.aouttype.c $(CTFCONVERT) -i -L VERSION uctf/tst.aouttype.o diff --git a/usr/src/cmd/dtrace/test/tst/common/bitfields/tst.bitfields.c b/usr/src/cmd/dtrace/test/tst/common/bitfields/tst.bitfields.c new file mode 100644 index 0000000000..180127191a --- /dev/null +++ b/usr/src/cmd/dtrace/test/tst/common/bitfields/tst.bitfields.c @@ -0,0 +1,92 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2022 Oxide Computer Company + */ + +/* + * This is designed to allow us to execute print() and various dereferencing + * operations with bitfields. It reads the values from argc and passes them to + * functions that we can then take apart. Crtitically this uses bitfields + * constructed via CTF and not the D compiler. + */ + +#include <err.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdlib.h> +#include <errno.h> + +typedef struct bit0 { + uint32_t a:3; + uint32_t b:2; + uint32_t c:1; + uint32_t d:1; + uint32_t e:1; + uint32_t f:1; + uint32_t g:3; + uint32_t h:3; + uint32_t i:5; + uint32_t j:4; + uint32_t k:6; + uint32_t l:1; + uint32_t m:1; +} bit0_t; + +typedef struct bit1 { + uint16_t a:1; + uint16_t b:8; + uint16_t c:3; + uint16_t d:2; + uint16_t e:1; + uint16_t f:1; +} bit1_t; + +void +mumble(FILE *f, bit0_t *zero, bit1_t *one) +{ + (void) fprintf(f, "%u\n%u\n", zero->k, one->d); +} + +int +main(int argc, char *argv[]) +{ + unsigned long l; + uint16_t u16; + uint32_t u32; + FILE *f; + + if (argc != 3) { + errx(EXIT_FAILURE, "Need two ints"); + } + + f = fopen("/dev/null", "rw+"); + if (f == NULL) { + err(EXIT_FAILURE, "failed to open /dev/null"); + } + + errno = 0; + l = strtoul(argv[1], NULL, 0); + if (errno != 0 || l == 0 || l > UINT16_MAX) { + errx(EXIT_FAILURE, "invalid u16 value: %s", argv[1]); + } + u16 = (uint16_t)l; + + l = strtoul(argv[2], NULL, 0); + if (errno != 0 || l == 0 || l > UINT32_MAX) { + errx(EXIT_FAILURE, "invalid u32 value: %s", argv[1]); + } + u32 = (uint32_t)l; + mumble(f, (bit0_t *)&u32, (bit1_t *)&u16); + + return (0); +} diff --git a/usr/src/cmd/dtrace/test/tst/common/bitfields/tst.bitfields.ksh b/usr/src/cmd/dtrace/test/tst/common/bitfields/tst.bitfields.ksh new file mode 100644 index 0000000000..b79046ba62 --- /dev/null +++ b/usr/src/cmd/dtrace/test/tst/common/bitfields/tst.bitfields.ksh @@ -0,0 +1,63 @@ +#!/usr/bin/ksh +# +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2022 Oxide Computer Company +# + +# +# This test acts as a series of regression tests in DTrace around +# printing bitfields that are byte sized at non-byte aligned offsets and +# around printing fields that are less than a byte in size, but due to their +# offset, cross a byte boundary (e.g. a 5-bit bitfield that starts at +# bit 6). +# +# The DTrace implementation has two different general paths for this: +# +# o The D compiler compiling a dereference into DIF code to be executed +# in probe context to extract a bitfield value. +# o The print() action which grabs the larger chunk of memory and then +# processes it all in userland. +# + +if [ $# != 1 ]; then + echo expected one argument: '<'dtrace-path'>' + exit 2 +fi + +dtrace=$1 +exe="tst.bitfields.exe" + +elfdump "./$exe" | grep -q '.SUNW_ctf' +if (( $? != 0 )); then + echo "CTF does not exist in $exe, that's a bug" >&2 + exit 1 +fi + +$dtrace -qs /dev/stdin -c "./$exe 0xe417 0x9391d7db" <<EOF +pid\$target::mumble:entry +{ + print(*args[1]); + printf("\n"); + print(*args[2]); + printf("\n"); + trace(args[2]->b); + printf("\n0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", args[2]->a, args[2]->b, + args[2]->c, args[2]->d, args[2]->e, args[2]->f); + trace(args[1]->i); + printf("\n0x%x 0x%x 0x%x 0x%x\n", args[1]->g, args[1]->h, args[1]->i, + args[1]->j); +} +EOF + +exit $rc diff --git a/usr/src/cmd/dtrace/test/tst/common/bitfields/tst.bitfields.ksh.out b/usr/src/cmd/dtrace/test/tst/common/bitfields/tst.bitfields.ksh.out new file mode 100644 index 0000000000..8db1736859 --- /dev/null +++ b/usr/src/cmd/dtrace/test/tst/common/bitfields/tst.bitfields.ksh.out @@ -0,0 +1,28 @@ +bit0_t { + unsigned int:3 a :3 = 0x3 + unsigned int:2 b :2 = 0x3 + unsigned int:1 c :1 = 0 + unsigned int:1 d :1 = 0x1 + unsigned int:1 e :1 = 0x1 + unsigned int:1 f :1 = 0x1 + unsigned int:3 g :3 = 0x3 + unsigned int:3 h :3 = 0x5 + unsigned int:5 i :5 = 0x3 + unsigned int:4 j :4 = 0x9 + unsigned int:6 k :6 = 0x13 + unsigned int:1 l :1 = 0 + unsigned int:1 m :1 = 0x1 +} +bit1_t { + unsigned short:1 a :1 = 0x1 + unsigned short:8 b :8 = 0xb + unsigned short:3 c :3 = 0x2 + unsigned short:2 d :2 = 0x2 + unsigned short:1 e :1 = 0x1 + unsigned short:1 f :1 = 0x1 +} +11 +0x1 0xb 0x2 0x2 0x1 0x1 +3 +0x3 0x5 0x3 0x9 + 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 6a854c5919..52e8bdcbf1 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 */ @@ -652,6 +653,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/pkg/manifests/system-dtrace-tests.p5m b/usr/src/pkg/manifests/system-dtrace-tests.p5m index 49529498f3..9185e36a0a 100644 --- a/usr/src/pkg/manifests/system-dtrace-tests.p5m +++ b/usr/src/pkg/manifests/system-dtrace-tests.p5m @@ -352,6 +352,9 @@ file \ mode=0444 file path=opt/SUNWdtrt/tst/common/bitfields/tst.BitFieldPromotion.d mode=0444 file path=opt/SUNWdtrt/tst/common/bitfields/tst.SizeofBitField.d mode=0444 +file path=opt/SUNWdtrt/tst/common/bitfields/tst.bitfields.exe mode=0555 +file path=opt/SUNWdtrt/tst/common/bitfields/tst.bitfields.ksh mode=0444 +file path=opt/SUNWdtrt/tst/common/bitfields/tst.bitfields.ksh.out mode=0444 dir path=opt/SUNWdtrt/tst/common/buffering file path=opt/SUNWdtrt/tst/common/buffering/err.end.d mode=0444 file path=opt/SUNWdtrt/tst/common/buffering/err.resize1.d mode=0444 |