Skip to content

Commit

Permalink
parser: support slices of typedefs, etc
Browse files Browse the repository at this point in the history
Slices in CTF are almost totally transparent to the user, *except* that
ctf_type_resolve will halt when it encounters a slice and will drill no
further, since going further would lose information about the encoding
of the slice.  Since you can have slices of typedefs, this means you
can't rely on ctf_type_resolve getting rid of all typedefs any more.

This change drills through to base types where necessary.  We have to do
it by hand in every place it's needed, which is fairly unpleasant.  I
think I caught them all (most are covered by the tests added here).  If
we find other places where spurious errors citing bitfields which should
have been treated as integral types appear, we can fix them as they crop
up.

Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
Reviewed-by: Kris Van Hees <kris.van.hees@oracle.com>
  • Loading branch information
nickalcock authored and kvanhees committed Jul 29, 2022
1 parent be2bd54 commit e437349
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 18 deletions.
78 changes: 60 additions & 18 deletions libdtrace/dt_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,36 @@ dt_type_name(ctf_file_t *ctfp, ctf_id_t type, char *buf, size_t len)
return buf;
}

/* Peer through slices, cv-quals and typedefs to their base type. */
ctf_id_t
dt_type_basetype(ctf_file_t *fp, ctf_id_t type)
{
ctf_id_t newtype;
uint_t kind;

type = ctf_type_resolve(fp, type);
kind = ctf_type_kind(fp, type);

/*
* Bitfields can be of typedef type, but we don't want to
* elide pointers.
*/
while ((kind == CTF_K_INTEGER || kind == CTF_K_ENUM ||
kind == CTF_K_FLOAT || kind == CTF_K_TYPEDEF)
&& (newtype = ctf_type_reference(fp, type)) != CTF_ERR) {
type = ctf_type_resolve(fp, newtype);
kind = ctf_type_kind (fp, type);
}

return type;
}

ctf_id_t
dt_node_basetype(const dt_node_t *dnp)
{
return dt_type_basetype(dnp->dn_ctfp, dnp->dn_type);
}

/*
* Perform the "usual arithmetic conversions" to determine which of the two
* input operand types should be promoted and used as a result type. The
Expand All @@ -297,15 +327,16 @@ dt_type_promote(dt_node_t *lp, dt_node_t *rp, ctf_file_t **ofp, ctf_id_t *otype)
{
ctf_file_t *lfp = lp->dn_ctfp;
ctf_id_t ltype = lp->dn_type;
ctf_id_t lbasetype = dt_node_basetype(lp);
uint_t lkind = ctf_type_kind(lfp, lbasetype);

ctf_file_t *rfp = rp->dn_ctfp;
ctf_id_t rtype = rp->dn_type;
ctf_id_t rbasetype = dt_node_basetype(rp);
uint_t rkind = ctf_type_kind(rfp, rbasetype);

ctf_id_t lbase = ctf_type_resolve(lfp, ltype);
uint_t lkind = ctf_type_kind(lfp, lbase);

ctf_id_t rbase = ctf_type_resolve(rfp, rtype);
uint_t rkind = ctf_type_kind(rfp, rbase);

dtrace_hdl_t *dtp = yypcb->pcb_hdl;
ctf_encoding_t le, re;
Expand Down Expand Up @@ -640,7 +671,8 @@ void
dt_node_type_assign(dt_node_t *dnp, ctf_file_t *fp, ctf_id_t type)
{
ctf_id_t base = ctf_type_resolve(fp, type);
uint_t kind = ctf_type_kind(fp, base);
ctf_id_t basetype = dt_type_basetype(fp, base);
uint_t kind = ctf_type_kind(fp, basetype);
ctf_encoding_t e;

/*
Expand Down Expand Up @@ -823,12 +855,14 @@ dt_node_is_integer(const dt_node_t *dnp)
ctf_file_t *fp = dnp->dn_ctfp;
ctf_encoding_t e;
ctf_id_t type;
ctf_id_t basetype;
uint_t kind;

assert(dnp->dn_flags & DT_NF_COOKED);

type = ctf_type_resolve(fp, dnp->dn_type);
kind = ctf_type_kind(fp, type);
basetype = dt_node_basetype(dnp);
kind = ctf_type_kind(fp, basetype);

if (kind == CTF_K_INTEGER &&
ctf_type_encoding(fp, type, &e) == 0 && IS_VOID(e))
Expand All @@ -842,13 +876,14 @@ dt_node_is_float(const dt_node_t *dnp)
{
ctf_file_t *fp = dnp->dn_ctfp;
ctf_encoding_t e;
ctf_id_t type;
ctf_id_t type, basetype;
uint_t kind;

assert(dnp->dn_flags & DT_NF_COOKED);

type = ctf_type_resolve(fp, dnp->dn_type);
kind = ctf_type_kind(fp, type);
basetype = dt_node_basetype(dnp);
kind = ctf_type_kind(fp, basetype);

return kind == CTF_K_FLOAT &&
ctf_type_encoding(dnp->dn_ctfp, type, &e) == 0 && (
Expand All @@ -861,13 +896,14 @@ dt_node_is_scalar(const dt_node_t *dnp)
{
ctf_file_t *fp = dnp->dn_ctfp;
ctf_encoding_t e;
ctf_id_t type;
ctf_id_t type, basetype;
uint_t kind;

assert(dnp->dn_flags & DT_NF_COOKED);

type = ctf_type_resolve(fp, dnp->dn_type);
kind = ctf_type_kind(fp, type);
basetype = dt_node_basetype(dnp);
kind = ctf_type_kind(fp, basetype);

if (kind == CTF_K_INTEGER &&
ctf_type_encoding(fp, type, &e) == 0 && IS_VOID(e))
Expand All @@ -882,13 +918,14 @@ dt_node_is_arith(const dt_node_t *dnp)
{
ctf_file_t *fp = dnp->dn_ctfp;
ctf_encoding_t e;
ctf_id_t type;
ctf_id_t type, basetype;
uint_t kind;

assert(dnp->dn_flags & DT_NF_COOKED);

type = ctf_type_resolve(fp, dnp->dn_type);
kind = ctf_type_kind(fp, type);
basetype = dt_node_basetype(dnp);
kind = ctf_type_kind(fp, basetype);

if (kind == CTF_K_INTEGER)
return ctf_type_encoding(fp, type, &e) == 0 && !IS_VOID(e);
Expand All @@ -901,7 +938,7 @@ dt_node_is_vfptr(const dt_node_t *dnp)
{
ctf_file_t *fp = dnp->dn_ctfp;
ctf_encoding_t e;
ctf_id_t type;
ctf_id_t type, basetype;
uint_t kind;

assert(dnp->dn_flags & DT_NF_COOKED);
Expand All @@ -911,7 +948,8 @@ dt_node_is_vfptr(const dt_node_t *dnp)
return 0; /* type is not a pointer */

type = ctf_type_resolve(fp, ctf_type_reference(fp, type));
kind = ctf_type_kind(fp, type);
basetype = dt_type_basetype(fp, type);
kind = ctf_type_kind(fp, basetype);

return kind == CTF_K_FUNCTION || (kind == CTF_K_INTEGER &&
ctf_type_encoding(fp, type, &e) == 0 && IS_VOID(e));
Expand Down Expand Up @@ -1006,7 +1044,7 @@ dt_node_is_void(const dt_node_t *dnp)
{
ctf_file_t *fp = dnp->dn_ctfp;
ctf_encoding_t e;
ctf_id_t type;
ctf_id_t type, basetype;

if (dt_node_is_dynamic(dnp))
return 0; /* <DYN> is an alias for void but not the same */
Expand All @@ -1018,8 +1056,9 @@ dt_node_is_void(const dt_node_t *dnp)
return 0;

type = ctf_type_resolve(fp, dnp->dn_type);
basetype = dt_node_basetype(dnp);

return ctf_type_kind(fp, type) == CTF_K_INTEGER &&
return ctf_type_kind(fp, basetype) == CTF_K_INTEGER &&
ctf_type_encoding(fp, type, &e) == 0 && IS_VOID(e);
}

Expand Down Expand Up @@ -1667,12 +1706,14 @@ dt_node_decl(void)
ctf_encoding_t cte;
ctf_arinfo_t r;
ctf_id_t etype;
ctf_id_t basetype;
uint_t kind;
uint_t alignment = 8;
uint_t size;

type = ctf_type_resolve(dtt.dtt_ctfp, dtt.dtt_type);
kind = ctf_type_kind(dtt.dtt_ctfp, type);
basetype = dt_type_basetype(dtt.dtt_ctfp, dtt.dtt_type);
kind = ctf_type_kind(dtt.dtt_ctfp, basetype);
size = ctf_type_size(dtt.dtt_ctfp, dtt.dtt_type);

switch (kind) {
Expand Down Expand Up @@ -3001,7 +3042,7 @@ dt_cook_op1(dt_node_t *dnp, uint_t idflags)

ctf_encoding_t e;
ctf_arinfo_t r;
ctf_id_t type, base;
ctf_id_t type, base, basetype;
uint_t kind;

if (dnp->dn_op == DT_TOK_PREINC || dnp->dn_op == DT_TOK_POSTINC ||
Expand Down Expand Up @@ -3068,7 +3109,8 @@ dt_cook_op1(dt_node_t *dnp, uint_t idflags)

dt_node_type_assign(dnp, cp->dn_ctfp, type);
base = ctf_type_resolve(cp->dn_ctfp, type);
kind = ctf_type_kind(cp->dn_ctfp, base);
basetype = dt_type_basetype (cp->dn_ctfp, type);
kind = ctf_type_kind(cp->dn_ctfp, basetype);

if (kind == CTF_K_INTEGER && ctf_type_encoding(cp->dn_ctfp,
base, &e) == 0 && IS_VOID(e)) {
Expand Down
25 changes: 25 additions & 0 deletions test/unittest/bitfields/tst.bitfield-is-integer.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Oracle Linux DTrace.
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/

/*
* ASSERTION:
* Bitfields are treated as integers.
*
* SECTION: Types, Operators, and Expressions/Bitwise Operators
*/

#pragma D option quiet

/* @@runtest-opts: -e */

/* @@trigger: bogus-ioctl */

syscall::ioctl:entry / curthread->frozen == 0 /
{ exit(0); }

syscall::ioctl:entry / curthread->frozen != 0 /
{ exit(0); }
28 changes: 28 additions & 0 deletions test/unittest/bitfields/tst.slices.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Oracle Linux DTrace.
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/

/*
* Check that lookup of types in CTF that happen to be bitfields works.
* (These types are represented as slices.)
* We are only interested in whether they parse, so exit immediately
* after that.
*/

/* @@runtest-opts: -e */

#pragma D option quiet

syscall::ioctl:entry
{
trace(curthread->sched_reset_on_fork);
}

fbt::tcp_parse_options:entry
{
/* dtv2: use args[2] later */
trace(((struct sk_buff *)arg2)->nohdr);
}

0 comments on commit e437349

Please sign in to comment.