[DTrace-devel] [PATCH 1/3] Add support for the link_ntop() subroutine

Eugene Loh eugene.loh at oracle.com
Mon Dec 11 22:03:05 UTC 2023


On 12/9/23 00:29, Kris Van Hees wrote:

> On Tue, Aug 29, 2023 at 09:54:31PM -0400, eugene.loh at oracle.com wrote:
>> diff --git a/bpf/link_ntop.S b/bpf/link_ntop.S
>> new file mode 100644
>> @@ -0,0 +1,127 @@
>> +#define ARPHRD_ETHER		1
>> +#define ARPHRD_INFINIBAND	32
> Maybe add that these coe from <linux/if_arp.h> ?

Maybe.  But that starts a cascade of other stuff that gets included.

In particular, if I understand correctly, we do not include 
/usr/include.  We include build/include, which has symlinks to various 
/usr/include/ directories.  The cascade leads to adding directories 
sys/, gnu/, bits/, etc., as well as files features.h, stdc-predef.h, 
etc.  We cannot just turn build/include into a link to /usr/include 
since then we could not touch .dir.stamp.  So, since we do not actually 
include /usr/include, it feels to me like these two #define make some 
sense.  Much simpler.

>> diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
>> @@ -6039,6 +6039,31 @@ dt_cg_subr_inet_ntop(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
>>   	emit(dlp,  BPF_ALU64_IMM(BPF_ADD, dnp->dn_reg, tstring_offset));
>>   }
>>   
>> +/* Definitions from libdtrace/net.d or /usr/include/linux/if_arp.h. */
>> +#define ARPHRD_ETHER         1
>> +#define ARPHRD_INFINIBAND   32
> Why not simply include <linux/if_arp.h> ?

Yeah, though mimicking what's done in the bpf .S file also makes sense, 
and there (per earlier discussion) including if_arp.h gets complicated.

>> +
>> +static void
>> +dt_cg_subr_link_ntop(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
>> +{
>> +	dt_node_t	*type = dnp->dn_args;
>> +	uint_t		Lokay = dt_irlist_label(dlp);
>> +
>> +	/* Determine type and check it is okay. */
>> +	dt_cg_node(type, dlp, drp);
>> +	emit(dlp,  BPF_BRANCH_IMM(BPF_JEQ, type->dn_reg, ARPHRD_INFINIBAND, Lokay));
>> +	emit(dlp,  BPF_BRANCH_IMM(BPF_JEQ, type->dn_reg, ARPHRD_ETHER, Lokay));
>> +	dt_cg_probe_error(yypcb, DTRACEFLT_ILLOP, DT_ISREG, type->dn_reg);
>> +	emitl(dlp, Lokay,
>> +		   BPF_NOP());
>> +
>> +	/* Move addr into dnp->dn_args so we can call dt_cg_subr_arg_to_tstring(). */
>> +	dnp->dn_args = type->dn_list;
> You probably should do this in a way that after the dt_cg_subr_arg_to_tstring()
> call, you can restore the node structure.  I.e. dnp->dn_args = type.  That way,
> depending on what type is, dt_node_free() will ensure proper cleanup is done
> when dt_node_free( is done on dnp.

Okay.

> But worse, this causes the dt_cg_check_ptr_arg() in dt_cg_subr_arg_to_tstring()
> to get bypassed (and thus err.link_ntopbadaddr.d fails) because you move the
> 2nd argument into the 1st argument spot, and then dt_cg_subr_arg_to_tstring()
> checks the type of the *1st* argument of link_type() according to its
> prototype.  And since that is not a pointer, the check is never done.

I don't follow.  dt_cg_subr_arg_to_tstring() checks the type of its 1st 
arg, which is the 2nd arg to link_ntop().  E.g., for 
err.link_ntopbadaddr.d, it's a pointer.  So that 2nd link_ntop() arg 
*is* a pointer, we do in fact run dt_cg_check_ptr_arg(), the NULL 
pointer is rejected, and the test passes.

Is err.link_ntopbadaddr.d really failing?

> Rather than remapping the args (exchanging type and addr), I think you need
> to keep them as they are, and do (assuming addr = dnp->dn_args):

How can we assume addr=dnp->dn_args?  The first arg of link_ntop() -- 
that is, dnp->dn_args -- is the type.

> 	dt_cg_node(addr, dlp, drp);
> 	dt_cg_check_ptr_arg(dlp, drp, addr, NULL);
> 	dt_cg_subr_arg_to_tstring(dnp, dlp, drp, "dt_link_ntop", DT_ISREG, addr->dn_reg, DT_IGNOR, 0);
>
> But then you do need to rework dt_link_ntop to accept type as the main argument
> and addr as the extra argument.
>
>> +
>> +	dt_cg_subr_arg_to_tstring(dnp, dlp, drp, "dt_link_ntop", DT_ISREG, type->dn_reg);
>> +	dt_regset_free(drp, type->dn_reg);
>> +}



More information about the DTrace-devel mailing list