Skip to content

Commit

Permalink
libdtrace: Be less strict when comparing pointer types
Browse files Browse the repository at this point in the history
If one of two pointers refers to a forward declaration, let the pointers
be compatible so long as the referred types have the same name.
Otherwise we can get spurious errors.

To give a specific example, this can happen when ipfw_nat.ko is loaded
before ipfw.ko and /usr/lib/dtrace/ipfw.d is processed.  Currently,
ipfw_nat.ko does not have a definition for struct inpcb (i.e., none of
its files include in_pcb.h), so in the CTF type graph, struct
ip_fw_args' "inp" member refers to a forward declaration, represented in
CTF with CTF_K_FORWARD.

Then, when libdtrace processes the ipfw_match_info_t translator in
ipfw.d, it decides that the "inp" field assignment is incorrect because
the two pointers are incompatible.  However, there's no harm in allowing
this assignment.  Add some logic to dt_node_is_ptrcompat() to detect
this case and declare the pointers as compatible so long as the name of
the thing they refer to is the same, similar to how any pointer is
compatible with a void *.

Reported by:	marck
Reviewed by:	Domagoj Stolfa <[email protected]>
MFC after:	2 weeks
Differential Revision:	https://reviews.freebsd.org/D48254
  • Loading branch information
markjdb committed Jan 1, 2025
1 parent b55baa8 commit 4196f22
Showing 1 changed file with 23 additions and 0 deletions.
23 changes: 23 additions & 0 deletions cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -1130,6 +1130,29 @@ dt_node_is_ptrcompat(const dt_node_t *lp, const dt_node_t *rp,
lp_is_void = ctf_type_encoding(lfp, lref, &e) == 0 && IS_VOID(e);
rp_is_void = ctf_type_encoding(rfp, rref, &e) == 0 && IS_VOID(e);

/*
* Let a pointer to a forward declaration be compatible with a pointer
* to a struct or union of the same name.
*/
if (lkind == CTF_K_POINTER && rkind == CTF_K_POINTER) {
int lrkind, rrkind;

lrkind = ctf_type_kind(lfp, lref);
rrkind = ctf_type_kind(rfp, rref);
if (lrkind == CTF_K_FORWARD || rrkind == CTF_K_FORWARD) {
const char *lname, *rname;
char ln[DT_TYPE_NAMELEN], rn[DT_TYPE_NAMELEN];

lname = ctf_type_name(lfp, lref, ln, sizeof (ln));
rname = ctf_type_name(rfp, rref, rn, sizeof (rn));
if (lname != NULL && rname != NULL &&
strcmp(lname, rname) == 0) {
lp_is_void = lrkind == CTF_K_FORWARD;
rp_is_void = rrkind == CTF_K_FORWARD;
}
}
}

/*
* The types are compatible if both are pointers to the same type, or
* if either pointer is a void pointer. If they are compatible, set
Expand Down

0 comments on commit 4196f22

Please sign in to comment.