[DTrace-devel] [PATCH v5] Add support for uregs[]

Eugene Loh eugene.loh at oracle.com
Mon Feb 27 02:02:16 UTC 2023


On 2/26/23 19:55, Kris Van Hees wrote:

> On Sun, Feb 26, 2023 at 07:45:40PM -0500, eugene.loh--- via DTrace-devel wrote:
>> diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
>> index 9f0675fa..ebd9a81c 100644
>> --- a/libdtrace/dt_cg.c
>> +++ b/libdtrace/dt_cg.c
>> @@ -3944,6 +3944,92 @@ dt_cg_assoc_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
>>   	TRACE_REGSET("    assoc_op: End  ");
>>   }
>>   
>> +static void
>> +dt_cg_uregs(unsigned int idx, dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
>> +{
>> +	dtrace_hdl_t *dtp = yypcb->pcb_hdl;
>> +
>> +	/* check if out-of-bounds */
>> +	if (idx >= sizeof(dt_pt_regs) / sizeof(uint64_t)) {
>> +
>> +#if defined(__amd64)
>> +		/*
>> +		 * Even if out-of-bounds, on x86 there are still a few
>> +		 * indices that are used to access task->thread. members.
>> +		 */
>> +		if (idx <= 25) {
>> +			ctf_file_t *cfp = dtp->dt_shared_ctf;
>> +			ctf_id_t type;
>> +			ctf_membinfo_t ctm;
>> +			int offset, rc;
>> +
>> +			/* look up task->thread offset */
>> +			if (!cfp)
>> +				longjmp(yypcb->pcb_jmpbuf, EDT_NOCTF);
>> +
>> +			type = ctf_lookup_by_name(cfp, "struct task_struct");
>> +			if (type == CTF_ERR)
>> +				longjmp(yypcb->pcb_jmpbuf, EDT_NOCTF);
>> +			if (ctf_member_info(cfp, type, "thread", &ctm) == CTF_ERR)
>> +				longjmp(yypcb->pcb_jmpbuf, EDT_NOCTF);
>> +			offset = ctm.ctm_offset / NBBY;
>> +
>> +			/* add the thread->member offset */
>> +			type = ctf_lookup_by_name(cfp, "struct thread_struct");
>> +			if (type == CTF_ERR)
>> +				longjmp(yypcb->pcb_jmpbuf, EDT_NOCTF);
>> +			switch (idx) {
>> +			case 21: rc = ctf_member_info(cfp, type, "ds", &ctm); break;
>> +			case 22: rc = ctf_member_info(cfp, type, "es", &ctm); break;
>> +			case 23: rc = ctf_member_info(cfp, type, "fsbase", &ctm); break;
>> +			case 24: rc = ctf_member_info(cfp, type, "gsbase", &ctm); break;
>> +			case 25: rc = ctf_member_info(cfp, type, "trap_nr", &ctm); break;
>> +			}
>> +			if (rc == -1)
>> +				longjmp(yypcb->pcb_jmpbuf, EDT_NOCTF);
>> +			offset += ctm.ctm_offset / NBBY;
>> +
>> +			/* copy task->thread.member onto the stack */
>> +			if (dt_regset_xalloc_args(drp) == -1)
>> +				longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
>> +			dt_regset_xalloc(drp, BPF_REG_0);
>> +			emit(dlp, BPF_CALL_HELPER(BPF_FUNC_get_current_task));
>> +			emit(dlp, BPF_MOV_REG(BPF_REG_3, BPF_REG_0));
>> +			emit(dlp, BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, offset));
>> +			emit(dlp, BPF_MOV_IMM(BPF_REG_2, sizeof(uint64_t)));
>> +			emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_1, BPF_REG_FP, DT_STK_SP));
>> +			emit(dlp, BPF_CALL_HELPER(dtp->dt_bpfhelper[BPF_FUNC_probe_read_kernel]));
>> +			dt_regset_free_args(drp);
>> +			emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_0, BPF_REG_FP, DT_STK_SP));
>> +			emit(dlp, BPF_LOAD(BPF_DW, dnp->dn_reg, BPF_REG_0, 0));
>> +			dt_regset_free(drp, BPF_REG_0);
>> +
>> +			return;
>> +		}
>> +#endif
>> +
>> +		dnerror(dnp, D_UNKNOWN, "uregs[]: index out of bounds (%d)\n", idx);
>> +
>> +		return;
>> +	}
>> +
>> +	/* if in-bounds, look up pt_regs[] */
>> +	if (dtp->dt_bpfhelper[BPF_FUNC_get_current_task_btf] == BPF_FUNC_unspec
>> +	  || dtp->dt_bpfhelper[BPF_FUNC_task_pt_regs] == BPF_FUNC_unspec)
>> +		dnerror(dnp, D_UNKNOWN, "uregs[] is not supported on this kernel\n");
> Can we move this to the beginning of the function, since really, if these
> helpers do not exist, it is more consistent (as you mentioned before) to not
> handle *any* indexing of uregs[].

As I mentioned before???  I think I was trying to say that the 
"consistent" error message did not make sense to me.  That is, if a user 
is interested in one of the task->thread. members, why should they be 
refused?  For reasons related to other, uninteresting (to them), 
uregs[]?  Users should not be refused features because unrelated 
features don't work.

Anyhow, you get the last word on this.  You can r-b or just let me know 
and I'll post a v6 with your proposed change.

>> +
>> +	if (dt_regset_xalloc_args(drp) == -1)
>> +		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
>> +	dt_regset_xalloc(drp, BPF_REG_0);
>> +	emit(dlp, BPF_CALL_HELPER(BPF_FUNC_get_current_task_btf));
>> +	emit(dlp, BPF_MOV_REG(BPF_REG_1, BPF_REG_0));
>> +	emit(dlp, BPF_CALL_HELPER(BPF_FUNC_task_pt_regs));
>> +	dt_regset_free_args(drp);
>> +	emit(dlp, BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, idx * sizeof(uint64_t)));
>> +	emit(dlp, BPF_LOAD(BPF_DW, dnp->dn_reg, BPF_REG_0, 0));
>> +	dt_regset_free(drp, BPF_REG_0);
>> +}
>> +
>>   /*
>>    * Currently, this code is only used for the args[] and uregs[] arrays.
>>    */



More information about the DTrace-devel mailing list