[DTrace-devel] [PATCH v4 02/10] cg: fault improvements

Kris Van Hees kris.van.hees at oracle.com
Wed Apr 13 16:23:33 UTC 2022


> Do not use regset allocation in dt_cg_probe_error on the grounds that
> spilling to the stack is pointless when the regs will all be thrown away
> in any case, and will trigger BPF verifier errors if some of the regs
> are not initialized, as is relatively likely in an error condition.
> 
> Also add an argument specifying whether the illegal value is actually
> a register whose value should be printed.  (Cases which don't care
> can just pass 0, 0).

Can you move the DT_ISREG / DT_ISIMM macros I add in [05/10]  (alloca deref)
here (and remove them from that patch) for consistency?  That makes it easier
to read the code in knowing what the argument value is.

So this will cuase a small change to this patch and to [05/10].

> Signed-off-by: Nick Alcock <nick.alcock at oracle.com>
> ---
>  libdtrace/dt_cg.c | 43 ++++++++++++++++++++++++++-----------------
>  1 file changed, 26 insertions(+), 17 deletions(-)
> 
> diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
> index a149c57529f1..80b93c91661b 100644
> --- a/libdtrace/dt_cg.c
> +++ b/libdtrace/dt_cg.c
> @@ -645,39 +645,48 @@ dt_cg_epilogue(dt_pcb_t *pcb)
>  
>  /*
>   * Generate code for a fault condition.  A call is made to dt_probe_error() to
> - * set the fault information.
> + * set the fault information.  ILL may be an absolute value or a register,
> + * depending on the value of ILLISREG.
> + *
> + * Doesn't use the regset code on the grounds that when this is executed we will
> + * never reuse any of the callers' regs in any case.
>   */
>  static void
> -dt_cg_probe_error(dt_pcb_t *pcb, uint32_t fault, uint64_t illval)
> +dt_cg_probe_error(dt_pcb_t *pcb, uint32_t fault, int illisreg, uint64_t ill)
>  {
>  	dt_irlist_t	*dlp = &pcb->pcb_ir;
> -	dt_regset_t	*drp = pcb->pcb_regs;
>  	dt_ident_t	*idp;
>  
>  	/*
>  	 *	dt_probe_error(
> -	 *		dctx,		// lddw %r1, %fp, DT_STK_DCT
> +	 *		dctx,		// lddw %r1, %fp, DT_STK_DCTX
>  	 *		PC,		// mov %r2, PC
>  	 *		fault,		// mov %r3, fault
>  	 *		illval);	// mov %r4, illval
>  	 *				// call dt_probe_error
>  	 *	return;			// exit
>  	 */
> -	if (dt_regset_xalloc_args(drp) == -1)
> -		longjmp(pcb->pcb_jmpbuf, EDT_NOREG);
> +
> +	/*
> +	 * Move the only pre-existing reg we need (ill) into place first,
> +	 * since we don't know which reg it is and it might perfectly well be
> +	 * one we are about to blindly reuse.
> +	 */
> +
> +	if (illisreg && ill != 4)
> +		emit(dlp, BPF_MOV_REG(BPF_REG_4, ill));
> +	else
> +		emit(dlp, BPF_MOV_IMM(BPF_REG_4, ill));
> +
>  	emit(dlp,  BPF_LOAD(BPF_DW, BPF_REG_1, BPF_REG_FP, DT_STK_DCTX));
>  	idp = dt_dlib_get_var(pcb->pcb_hdl, "PC");
>  	assert(idp != NULL);
>  	emite(dlp, BPF_MOV_IMM(BPF_REG_2, -1), idp);
> -	emit(dlp,  BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 4));
> +	emit(dlp,  BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 3));
>  	emit(dlp,  BPF_MOV_IMM(BPF_REG_3, fault));
> -	emit(dlp,  BPF_MOV_IMM(BPF_REG_4, illval));
> -	dt_regset_xalloc(drp, BPF_REG_0);
>  	idp = dt_dlib_get_func(pcb->pcb_hdl, "dt_probe_error");
>  	assert(idp != NULL);
>  	emite(dlp, BPF_CALL_FUNC(idp->di_id), idp);
> -	dt_regset_free_args(drp);
> -	dt_regset_free(drp, BPF_REG_0);
>  	emit(dlp,  BPF_RETURN());
>  }
>  
> @@ -691,7 +700,7 @@ dt_cg_check_notnull(dt_irlist_t *dlp, dt_regset_t *drp, int reg)
>  	uint_t	lbl_notnull = dt_irlist_label(dlp);
>  
>  	emit(dlp,  BPF_BRANCH_IMM(BPF_JNE, reg, 0, lbl_notnull));
> -	dt_cg_probe_error(yypcb, DTRACEFLT_BADADDR, 0);
> +	dt_cg_probe_error(yypcb, DTRACEFLT_BADADDR, 0, 0);
>  	emitl(dlp, lbl_notnull,
>  		   BPF_NOP());
>  }
> @@ -1652,7 +1661,7 @@ dt_cg_act_stack(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind)
>  	dt_regset_free_args(drp);
>  	emit(dlp,  BPF_BRANCH_IMM(BPF_JSGE, BPF_REG_0, 0, lbl_valid));
>  	dt_regset_free(drp, BPF_REG_0);
> -	dt_cg_probe_error(pcb, DTRACEFLT_BADSTACK, 0);
> +	dt_cg_probe_error(pcb, DTRACEFLT_BADSTACK, 0, 0);
>  	emitl(dlp, lbl_valid,
>  		   BPF_NOP());
>  }
> @@ -1822,7 +1831,7 @@ dt_cg_act_ustack(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind)
>  	dt_regset_free_args(drp);
>  	emit(dlp,  BPF_BRANCH_IMM(BPF_JSGE, BPF_REG_0, 0, lbl_valid));
>  	dt_regset_free(drp, BPF_REG_0);
> -	dt_cg_probe_error(pcb, DTRACEFLT_BADSTACK, 0);
> +	dt_cg_probe_error(pcb, DTRACEFLT_BADSTACK, 0, 0);
>  	emitl(dlp, lbl_valid,
>  		   BPF_NOP());
>  }
> @@ -2492,7 +2501,7 @@ dt_cg_arglist(dt_ident_t *idp, dt_node_t *args, dt_irlist_t *dlp,
>  			dt_regset_free_args(drp);
>  			emit(dlp,  BPF_BRANCH_IMM(BPF_JSGE, BPF_REG_0, 0, lbl_valid));
>  			dt_regset_free(drp, BPF_REG_0);
> -			dt_cg_probe_error(yypcb, DTRACEFLT_BADADDR, 128 + i);
> +			dt_cg_probe_error(yypcb, DTRACEFLT_BADADDR, 0, 128 + i);
>  			dt_regset_xalloc(drp, BPF_REG_0);
>  
>  			emitl(dlp, lbl_valid,
> @@ -2514,7 +2523,7 @@ dt_cg_arglist(dt_ident_t *idp, dt_node_t *args, dt_irlist_t *dlp,
>  			emit(dlp,  BPF_CALL_HELPER(BPF_FUNC_probe_read));
>  			dt_regset_free_args(drp);
>  			emit(dlp,  BPF_BRANCH_IMM(BPF_JEQ, BPF_REG_0, 0, lbl_valid));
> -			dt_cg_probe_error(yypcb, DTRACEFLT_BADADDR, 0);
> +			dt_cg_probe_error(yypcb, DTRACEFLT_BADADDR, 0, 0);
>  
>  			emitl(dlp, lbl_valid,
>  				   BPF_ALU64_IMM(BPF_ADD, treg, size));
> @@ -2797,7 +2806,7 @@ dt_cg_arithmetic_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp,
>  		/* First ensure we do not perform a division by zero. */
>  		emit(dlp,  BPF_BRANCH_IMM(BPF_JNE, dnp->dn_right->dn_reg, 0,
>  					  lbl_valid));
> -		dt_cg_probe_error(yypcb, DTRACEFLT_DIVZERO, 0);
> +		dt_cg_probe_error(yypcb, DTRACEFLT_DIVZERO, 0, 0);
>  		emitl(dlp, lbl_valid,
>  			   BPF_NOP());
>  
> -- 
> 2.35.1



More information about the DTrace-devel mailing list