[DTrace-devel] [PATCH v3 2/2] Extend the USDT bit mask to multiple words

Kris Van Hees kris.van.hees at oracle.com
Mon Nov 10 19:40:40 UTC 2025


The pid-specific uprobes support removes the code that this patch applies to,
so it is obsolete.

On Tue, Aug 19, 2025 at 05:07:15PM -0400, Kris Van Hees via DTrace-devel wrote:
> I would like to hold off on this patch a bit longer.  I don't think it is too
> likely people are running into toruble due to too many clauses, and it would
> be nice to avoid adding more provider-specific logic in the core of DTrace.
> 
> My suggestion is that we move the creation of the USDT-specific maps to the
> uprobe provider.  Since those maps are only ever used by the trampolines
> created by this provider, the fds and other data can be stored in the
> provider specific private data.  Upon first call to generate a trampoline we
> can check whether it has been initialized, and if not, create the maps and
> populate them.
> 
> This way all the USDT-specific handling remains within the uprobe provider,
> and we actually fix the earlier inclusion of creation of USDT maps by the
> generic code.
> 
> On Tue, Jul 22, 2025 at 08:53:04PM -0400, eugene.loh at oracle.com wrote:
> > From: Eugene Loh <eugene.loh at oracle.com>
> > 
> > Currently, USDT is limited to 64 probe descriptions since the
> > underlying probe uses a 64-bit mask to decide which probes to execute.
> > 
> > Change to a multi-word bit mask that can be extended to however many
> > probe descriptions there are.
> > 
> > Also, change the mask words to be 32-bit rather than 64-bit.  The reason
> > is that, commonly, there will be fewer than 32 probe descriptions.  In
> > this case, we shorten the value of the "USDT prids" BPF map from 16 bytes
> >         uint32_t        prid;
> >         long long       mask[1];
> > down to 8 bytes
> >         uint32_t        prid;
> >         uint32_t        mask[1];
> > (The second member is smaller and no longer costs extra padding.)
> > 
> > We also add an
> >         int dt_usdt_mask_bytes;
> > to denote how many bytes will be needed for the mask.  This value is
> > computed by usdt_mask_bytes_init().  Currently, this function is
> > awkwardly called in gmap_create_usdt(), just before the value is needed.
> > Such a call to a provider-specific function is clumsy, but there are no
> > other calls to the provider between compilation (where the number of
> > statements is determined) and this map creation.
> > 
> > Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
> > ---
> >  libdtrace/dt_bpf.c                            |   6 +-
> >  libdtrace/dt_bpf_maps.h                       |   4 +-
> >  libdtrace/dt_impl.h                           |   1 +
> >  libdtrace/dt_prov_uprobe.c                    |  87 +++++++++---
> >  .../unittest/usdt/tst.manyprobedescriptions.r |   1 +
> >  .../usdt/tst.manyprobedescriptions.sh         |  64 +++++++++
> >  .../usdt/tst.manyprobedescriptions2.r         |   1 +
> >  .../usdt/tst.manyprobedescriptions2.sh        | 127 ++++++++++++++++++
> >  8 files changed, 267 insertions(+), 24 deletions(-)
> >  create mode 100644 test/unittest/usdt/tst.manyprobedescriptions.r
> >  create mode 100755 test/unittest/usdt/tst.manyprobedescriptions.sh
> >  create mode 100644 test/unittest/usdt/tst.manyprobedescriptions2.r
> >  create mode 100755 test/unittest/usdt/tst.manyprobedescriptions2.sh
> > 
> > diff --git a/libdtrace/dt_bpf.c b/libdtrace/dt_bpf.c
> > index ddd849d0b..fcb53f044 100644
> > --- a/libdtrace/dt_bpf.c
> > +++ b/libdtrace/dt_bpf.c
> > @@ -967,6 +967,7 @@ gmap_create_probes(dtrace_hdl_t *dtp)
> >  	return 0;
> >  }
> >  
> > +void usdt_mask_bytes_init(dtrace_hdl_t *dtp);
> >  /*
> >   * Create the 'usdt_names' and 'usdt_prids' BPF maps.
> >   *
> > @@ -992,8 +993,11 @@ gmap_create_usdt(dtrace_hdl_t *dtp)
> >  	if (dtp->dt_usdt_namesmap_fd == -1)
> >  		return -1;
> >  
> > +	usdt_mask_bytes_init(dtp);
> > +
> >  	dtp->dt_usdt_pridsmap_fd = create_gmap(dtp, "usdt_prids", BPF_MAP_TYPE_HASH,
> > -	    sizeof(usdt_prids_map_key_t), sizeof(usdt_prids_map_val_t), nusdtprobes);
> > +	    sizeof(usdt_prids_map_key_t),
> > +	    sizeof(usdt_prids_map_val_t) + dtp->dt_usdt_mask_bytes, nusdtprobes);
> >  	if (dtp->dt_usdt_pridsmap_fd == -1)
> >  		return -1;
> >  
> > diff --git a/libdtrace/dt_bpf_maps.h b/libdtrace/dt_bpf_maps.h
> > index 884dc3983..ec5d4d7b1 100644
> > --- a/libdtrace/dt_bpf_maps.h
> > +++ b/libdtrace/dt_bpf_maps.h
> > @@ -1,6 +1,6 @@
> >  /*
> >   * Oracle Linux DTrace.
> > - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
> > + * Copyright (c) 2019, 2025, 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.
> >   */
> > @@ -48,7 +48,7 @@ typedef struct usdt_prids_map_key {
> >  } usdt_prids_map_key_t;
> >  typedef struct usdt_prids_map_val {
> >  	uint32_t	prid;		/* should be dtrace_id_t, sys/dtrace_types.h */
> > -	long long	mask;
> > +	uint32_t	mask[];
> >  } usdt_prids_map_val_t;
> >  
> >  #ifdef  __cplusplus
> > diff --git a/libdtrace/dt_impl.h b/libdtrace/dt_impl.h
> > index 2adc1252b..8bbc4dc1f 100644
> > --- a/libdtrace/dt_impl.h
> > +++ b/libdtrace/dt_impl.h
> > @@ -397,6 +397,7 @@ struct dtrace_hdl {
> >  	int dt_cpumap_fd;	/* file descriptor for the 'cpuinfo' BPF map */
> >  	int dt_usdt_pridsmap_fd; /* file descriptor for the 'usdt_prids' BPF map */
> >  	int dt_usdt_namesmap_fd; /* file descriptor for the 'usdt_names' BPF map */
> > +	int dt_usdt_mask_bytes;	/* size of USDT mask in bytes */
> >  	dtrace_handle_err_f *dt_errhdlr; /* error handler, if any */
> >  	void *dt_errarg;	/* error handler argument */
> >  	dtrace_handle_drop_f *dt_drophdlr; /* drop handler, if any */
> > diff --git a/libdtrace/dt_prov_uprobe.c b/libdtrace/dt_prov_uprobe.c
> > index e8f9f8c98..8b55fe319 100644
> > --- a/libdtrace/dt_prov_uprobe.c
> > +++ b/libdtrace/dt_prov_uprobe.c
> > @@ -403,7 +403,7 @@ clean_usdt_probes(dtrace_hdl_t *dtp)
> >  	int			fdprids = dtp->dt_usdt_pridsmap_fd;
> >  	int			fdnames = dtp->dt_usdt_namesmap_fd;
> >  	usdt_prids_map_key_t	key, nxt;
> > -	usdt_prids_map_val_t	val;
> > +	usdt_prids_map_val_t	*val = alloca(sizeof(usdt_prids_map_val_t) + dtp->dt_usdt_mask_bytes);
> >  	list_key_t		keys_to_delete, *elem, *elem_next;
> >  	dt_probe_t		*prp, *prp_next;
> >  
> > @@ -418,7 +418,7 @@ clean_usdt_probes(dtrace_hdl_t *dtp)
> >  	while (dt_bpf_map_next_key(fdprids, &key, &nxt) == 0) {
> >  		memcpy(&key, &nxt, sizeof(usdt_prids_map_key_t));
> >  
> > -		if (dt_bpf_map_lookup(fdprids, &key, &val) == -1)
> > +		if (dt_bpf_map_lookup(fdprids, &key, val) == -1)
> >  			return dt_set_errno(dtp, EDT_BPF);
> >  
> >  		/* Check if the process is still running. */
> > @@ -431,7 +431,7 @@ clean_usdt_probes(dtrace_hdl_t *dtp)
> >  			 * we might delete the same usdt_names entry
> >  			 * multiple times.  That's okay.
> >  			 */
> > -			dt_bpf_map_delete(fdnames, &val.prid);
> > +			dt_bpf_map_delete(fdnames, &val->prid);
> >  
> >  			/*
> >  			 * Delete the usdt_prids entry.
> > @@ -452,7 +452,7 @@ clean_usdt_probes(dtrace_hdl_t *dtp)
> >  		 * FIXME.  There might be another case, where the process
> >  		 * is still running, but some of its USDT probes are gone?
> >  		 * So maybe we have to check for the existence of one of
> > -		 *     dtrace_probedesc_t *pdp = dtp->dt_probes[val.prid]->desc;
> > +		 *     dtrace_probedesc_t *pdp = dtp->dt_probes[val->prid]->desc;
> >  		 *     char *prv = ...pdp->prv minus the numerial part;
> >  		 *
> >  		 *     /run/dtrace/probes/$pid/$pdp->prv/$pdp->mod/$pdp->fun/$pdp->prb
> > @@ -590,6 +590,31 @@ static void usdt_error(dt_pcb_t *pcb, const char *fmt, ...)
> >  	longjmp(pcb->pcb_jmpbuf, EDT_COMPILER);
> >  }
> >  
> > +void usdt_mask_bytes_init(dtrace_hdl_t *dtp)
> > +{
> > +	int i, n = 0, w = sizeof(((usdt_prids_map_val_t *)0)->mask[0]);
> > +
> > +	/* Count how many statements cannot be ignored, regardless of uprp. */
> > +	for (i = 0; i < dtp->dt_stmt_nextid; i++) {
> > +		dtrace_stmtdesc_t *stp;
> > +
> > +		stp = dtp->dt_stmts[i];
> > +		if (stp == NULL || ignore_clause(dtp, i, NULL))
> > +			continue;
> > +
> > +		n++;
> > +	}
> > +
> > +	/* Determine how many bytes are needed for this many bits. */
> > +	n = (n + CHAR_BIT - 1) / CHAR_BIT;
> > +
> > +	/* Determine how many words are needed for this many bytes. */
> > +	n = (n + w - 1) / w;
> > +
> > +	/* Determine how many bytes are needed. */
> > +	dtp->dt_usdt_mask_bytes = (n ? n : 1) * w;
> > +}
> > +
> >  static int add_probe_uprobe(dtrace_hdl_t *dtp, dt_probe_t *prp)
> >  {
> >  	dtrace_difo_t   *dp;
> > @@ -651,6 +676,7 @@ static int add_probe_usdt(dtrace_hdl_t *dtp, dt_probe_t *prp)
> >  	int				fd = dtp->dt_usdt_namesmap_fd;
> >  	pid_t				pid;
> >  	list_probe_t			*pup;
> > +	usdt_prids_map_val_t		*val;
> >  
> >  	/* Add probe name elements to usdt_names map. */
> >  	p = probnam;
> > @@ -686,11 +712,11 @@ static int add_probe_usdt(dtrace_hdl_t *dtp, dt_probe_t *prp)
> >  	}
> >  
> >  	/* Add prid and bit mask to usdt_prids map. */
> > +	val = alloca(sizeof(usdt_prids_map_val_t) + dtp->dt_usdt_mask_bytes);
> >  	for (pup = prp->prv_data; pup != NULL; pup = dt_list_next(pup)) {
> >  		dt_probe_t		*uprp = pup->probe;
> > -		long long		mask = 0, bit = 1;
> > +		uint32_t		iword = 0, mask = 0, bit = 1;
> >  		usdt_prids_map_key_t	key;
> > -		usdt_prids_map_val_t	val;
> >  		dt_uprobe_t		*upp = uprp->prv_data;
> >  
> >  		/*
> > @@ -704,15 +730,24 @@ static int add_probe_usdt(dtrace_hdl_t *dtp, dt_probe_t *prp)
> >  		if (uprp->prov->impl == &dt_uprobe && !(upp->flags & PP_IS_ENABLED)) {
> >  			int n;
> >  
> > +			/*
> > +			 * The loop over n to dtp->dt_stmt_nextid, skipping
> > +			 * ignore_clause(), should be the same here as in
> > +			 * the trampoline.
> > +			 */
> >  			for (n = 0; n < dtp->dt_stmt_nextid; n++) {
> >  				dtrace_stmtdesc_t *stp;
> >  
> >  				stp = dtp->dt_stmts[n];
> > -				if (stp == NULL)
> > +				if (stp == NULL || ignore_clause(dtp, n, uprp))
> >  					continue;
> >  
> > -				if (ignore_clause(dtp, n, uprp))
> > -					continue;
> > +				if (bit == 0) {
> > +					val->mask[iword] = mask;
> > +					mask = 0;
> > +					iword++;
> > +					bit = 1;
> > +				}
> >  
> >  				if (dt_gmatch(prp->desc->prv, stp->dtsd_ecbdesc->dted_probe.prv) &&
> >  				    dt_gmatch(prp->desc->mod, stp->dtsd_ecbdesc->dted_probe.mod) &&
> > @@ -727,11 +762,11 @@ static int add_probe_usdt(dtrace_hdl_t *dtp, dt_probe_t *prp)
> >  		key.pid = pid;
> >  		key.uprid = uprp->desc->id;
> >  
> > -		val.prid = prp->desc->id;
> > -		val.mask = mask;
> > +		val->prid = prp->desc->id;
> > +		val->mask[iword] = mask;
> >  
> >  		// FIXME Check return value, but how should errors be handled?
> > -		dt_bpf_map_update(dtp->dt_usdt_pridsmap_fd, &key, &val);
> > +		dt_bpf_map_update(dtp->dt_usdt_pridsmap_fd, &key, val);
> >  	}
> >  
> >  	return 0;
> > @@ -1452,7 +1487,7 @@ static int trampoline(dt_pcb_t *pcb, uint_t exitlbl)
> >  	const list_probe_t	*pop;
> >  	uint_t			lbl_exit = pcb->pcb_exitlbl;
> >  	dt_ident_t		*usdt_prids = dt_dlib_get_map(dtp, "usdt_prids");
> > -	int			n;
> > +	int			n, ibit, w = CHAR_BIT * sizeof(((usdt_prids_map_val_t *)0)->mask[0]);
> >  
> >  	assert(usdt_prids != NULL);
> >  
> > @@ -1539,7 +1574,8 @@ static int trampoline(dt_pcb_t *pcb, uint_t exitlbl)
> >  	 */
> >  	assert(sizeof(usdt_prids_map_key_t) <= DT_STK_SLOT_SZ);
> >  	emit(dlp,  BPF_STORE(BPF_W, BPF_REG_FP, DT_TRAMP_SP_SLOT(0), BPF_REG_0));
> > -	emit(dlp,  BPF_STORE_IMM(BPF_W, BPF_REG_FP, DT_TRAMP_SP_SLOT(0) + (int)sizeof(pid_t), uprp->desc->id));
> > +	emit(dlp,  BPF_STORE_IMM(BPF_W, BPF_REG_FP,
> > +		   DT_TRAMP_SP_SLOT(0) + (int)sizeof(pid_t), uprp->desc->id));
> >  	dt_cg_xsetx(dlp, usdt_prids, DT_LBL_NONE, BPF_REG_1, usdt_prids->di_id);
> >  	emit(dlp,  BPF_MOV_REG(BPF_REG_2, BPF_REG_FP));
> >  	emit(dlp,  BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, DT_TRAMP_SP_SLOT(0)));
> > @@ -1573,8 +1609,8 @@ static int trampoline(dt_pcb_t *pcb, uint_t exitlbl)
> >  	emit(dlp,  BPF_LOAD(BPF_W, BPF_REG_1, BPF_REG_0, 0));
> >  	emit(dlp,  BPF_STORE(BPF_W, BPF_REG_7, DMST_PRID, BPF_REG_1));
> >  
> > -	/* Read the bit mask from the table lookup in %r6. */    // FIXME someday, extend this past 64 bits
> > -	emit(dlp,  BPF_LOAD(BPF_DW, BPF_REG_6, BPF_REG_0, offsetof(usdt_prids_map_val_t, mask)));
> > +	/* Store the value key for reuse. */
> > +	emit(dlp,  BPF_STORE(BPF_DW, BPF_REG_FP, DT_TRAMP_SP_SLOT(0), BPF_REG_0));
> >  
> >  	/*
> >  	 * Apply arg mappings, if needed.
> > @@ -1588,21 +1624,29 @@ static int trampoline(dt_pcb_t *pcb, uint_t exitlbl)
> >  	/*
> >  	 * Hold the bit mask in %r6 between clause calls.
> >  	 */
> > -	for (n = 0; n < dtp->dt_stmt_nextid; n++) {
> > +	/*
> > +	 * The loop over n to dtp->dt_stmt_nextid, skipping
> > +	 * ignore_clause(), should be the same here as in
> > +	 * add_probe_usdt().
> > +	 */
> > +	for (ibit = n = 0; n < dtp->dt_stmt_nextid; n++) {
> >  		dtrace_stmtdesc_t *stp;
> >  		dt_ident_t	*idp;
> >  		uint_t		lbl_next;
> >  
> >  		stp = dtp->dt_stmts[n];
> > -		if (stp == NULL)
> > -			continue;
> > -
> > -		if (ignore_clause(dtp, n, uprp))
> > +		if (stp == NULL || ignore_clause(dtp, n, uprp))
> >  			continue;
> >  
> >  		idp = stp->dtsd_clause;
> >  		lbl_next = dt_irlist_label(dlp);
> >  
> > +		/* Load the next word of the bit mask into %r6. */
> > +		if (ibit % w == 0) {
> > +			emit(dlp,  BPF_LOAD(BPF_DW, BPF_REG_0, BPF_REG_FP, DT_TRAMP_SP_SLOT(0)));
> > +			emit(dlp,  BPF_LOAD(BPF_W, BPF_REG_6, BPF_REG_0, offsetof(usdt_prids_map_val_t, mask[ibit / w])));
> > +		}
> > +
> >  		/* If the lowest %r6 bit is 0, skip over this clause. */
> >  		emit(dlp,  BPF_MOV_REG(BPF_REG_1, BPF_REG_6));
> >  		emit(dlp,  BPF_ALU64_IMM(BPF_AND, BPF_REG_1, 1));
> > @@ -1630,6 +1674,7 @@ static int trampoline(dt_pcb_t *pcb, uint_t exitlbl)
> >  
> >  		/* Right-shift %r6. */
> >  		emit(dlp,  BPF_ALU64_IMM(BPF_RSH, BPF_REG_6, 1));
> > +		ibit++;
> >  	}
> >  
> >  out:
> > diff --git a/test/unittest/usdt/tst.manyprobedescriptions.r b/test/unittest/usdt/tst.manyprobedescriptions.r
> > new file mode 100644
> > index 000000000..2e9ba477f
> > --- /dev/null
> > +++ b/test/unittest/usdt/tst.manyprobedescriptions.r
> > @@ -0,0 +1 @@
> > +success
> > diff --git a/test/unittest/usdt/tst.manyprobedescriptions.sh b/test/unittest/usdt/tst.manyprobedescriptions.sh
> > new file mode 100755
> > index 000000000..92a61d5b7
> > --- /dev/null
> > +++ b/test/unittest/usdt/tst.manyprobedescriptions.sh
> > @@ -0,0 +1,64 @@
> > +#!/bin/bash
> > +#
> > +# Oracle Linux DTrace.
> > +# Copyright (c) 2025, 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.
> > +
> > +dtrace=$1
> > +TRIGGER=$PWD/test/triggers/usdt-tst-args
> > +
> > +DIRNAME="$tmpdir/usdt-many_probe_descriptions.$$.$RANDOM"
> > +mkdir -p $DIRNAME
> > +cd $DIRNAME
> > +
> > +# Construct the D scripts and output files.
> > +# We stick 80 probe descriptions in each of 3 scripts to test
> > +# USDT's ability to handle hundreds of probe descriptions.
> > +for d in 0 1 2; do
> > +for x in 00 01 02 03 04 05 06 07 08 09 \
> > +         10 11 12 13 14 15 16 17 18 19 \
> > +         20 21 22 23 24 25 26 27 28 29 \
> > +         30 31 32 33 34 35 36 37 38 39 \
> > +         40 41 42 43 44 45 46 47 48 49 \
> > +         50 51 52 53 54 55 56 57 58 59 \
> > +         60 61 62 63 64 65 66 67 68 69 \
> > +         70 71 72 73 74 75 76 77 78 79 \
> > +; do
> > +	echo 'test_prov$target:::place { printf("'$d$x'\n"); }' >> D$d.d
> > +	echo $d$x >> expect.txt
> > +done
> > +done
> > +echo 'test_prov$target:::place { exit(0); }' >> D$d.d
> > +echo >> expect.txt
> > +
> > +# Run DTrace.
> > +
> > +$dtrace $dt_flags -c $TRIGGER -q -s D0.d -s D1.d -s D2.d >& actual.txt
> > +if [ $? -eq 0 ]; then
> > +	if diff -q expect.txt actual.txt > /dev/null; then
> > +		echo success
> > +		exit 0
> > +	else
> > +		echo ERROR: did not get expected results
> > +		echo === expect.txt
> > +		cat      expect.txt
> > +		echo === actual.txt
> > +		cat      actual.txt
> > +		echo === diff
> > +		diff expect.txt actual.txt
> > +	fi
> > +else
> > +	echo ERROR: dtrace error
> > +	echo ==== output
> > +	cat actual.txt
> > +fi
> > +
> > +echo ==== script D0.d
> > +cat D0.d
> > +echo ==== script D1.d
> > +cat D1.d
> > +echo ==== script D2.d
> > +cat D2.d
> > +
> > +exit 1
> > diff --git a/test/unittest/usdt/tst.manyprobedescriptions2.r b/test/unittest/usdt/tst.manyprobedescriptions2.r
> > new file mode 100644
> > index 000000000..2e9ba477f
> > --- /dev/null
> > +++ b/test/unittest/usdt/tst.manyprobedescriptions2.r
> > @@ -0,0 +1 @@
> > +success
> > diff --git a/test/unittest/usdt/tst.manyprobedescriptions2.sh b/test/unittest/usdt/tst.manyprobedescriptions2.sh
> > new file mode 100755
> > index 000000000..8001cec0b
> > --- /dev/null
> > +++ b/test/unittest/usdt/tst.manyprobedescriptions2.sh
> > @@ -0,0 +1,127 @@
> > +#!/bin/bash
> > +#
> > +# Oracle Linux DTrace.
> > +# Copyright (c) 2025, 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.
> > +
> > +# This test uses many probes and probe descriptions.  Therefore, the
> > +# number of BPF programs to load into the kernel -- dt_bpf_load_prog()
> > +# calling prp->prov->impl->load_prog(), which is dt_bpf_prog_load() --
> > +# and the duration of each load are both increasing.
> > +# @@timeout: 400
> > +
> > +dtrace=$1
> > +
> > +DIRNAME="$tmpdir/usdt-many_probe_descriptions2.$$.$RANDOM"
> > +mkdir -p $DIRNAME
> > +cd $DIRNAME
> > +
> > +# Set the lists.
> > +# - The probes will be foo$x$y.
> > +# - The probe descriptions will be foo$x* and foo*$y, for each $d.
> > +# So if there are nx items in xlist, ny in ylist, and nd in dlist,
> > +# - there will be roughly nx*ny probes
> > +# - there will be roughly (nx+ny)*nd probe descriptions
> > +
> > +xlist="a b c d e f g h i j k l m"
> > +ylist="n o p q r s t u v w x y z"
> > +dlist="0 1 2 3 4 5 6 7 8"
> > +
> > +# Make the trigger:  Preambles.
> > +
> > +echo "provider testprov {" > prov.d
> > +
> > +echo '#include "prov.h"' > main.c
> > +echo 'int main(int argc, char **argv) {' >> main.c
> > +
> > +# Make the trigger:  Loop over the probes.
> > +
> > +for x in $xlist; do
> > +for y in $ylist; do
> > +    echo "probe foo$x$y();" >> prov.d
> > +    echo "TESTPROV_FOO$x$y();" | awk '{ print(toupper($1)) }' >> main.c
> > +done
> > +done
> > +
> > +# Make the trigger:  Epilogues.
> > +
> > +echo "};" >> prov.d
> > +echo "return 0; }" >> main.c
> > +
> > +# Build the trigger.
> > +
> > +$dtrace $dt_flags -h -s prov.d
> > +if [ $? -ne 0 ]; then
> > +	echo "failed to generate header file" >&2
> > +	cat prov.d
> > +	exit 1
> > +fi
> > +$CC $test_cppflags -c main.c
> > +if [ $? -ne 0 ]; then
> > +	echo "failed to compile test" >&2
> > +	cat main.c
> > +	exit 1
> > +fi
> > +$dtrace $dt_flags -G -64 -s prov.d main.o
> > +if [ $? -ne 0 ]; then
> > +	echo "failed to create DOF" >&2
> > +	exit 1
> > +fi
> > +$CC $test_ldflags -o main main.o prov.o
> > +if [ $? -ne 0 ]; then
> > +	echo "failed to link final executable" >&2
> > +	exit 1
> > +fi
> > +
> > +# Prepare the D script, generating the probe descriptions.
> > +
> > +rm -f D.d
> > +for d in $dlist; do
> > +	for x in $xlist; do
> > +		echo 'testprov$target:::foo'$x'* { printf("'$d' '$x'* %s\n", probename) }' >> D.d
> > +	done
> > +	for y in $ylist; do
> > +		echo 'testprov$target:::foo*'$y' { printf("'$d' *'$y' %s\n", probename) }' >> D.d
> > +	done
> > +done
> > +
> > +# Prepare the expected output.
> > +
> > +for x in $xlist; do
> > +for y in $ylist; do
> > +for d in $dlist; do
> > +	echo $d $x'*' foo$x$y >> expect.txt
> > +	echo $d '*'$y foo$x$y >> expect.txt
> > +done
> > +done
> > +done
> > +echo >> expect.txt
> > +
> > +# Run DTrace.
> > +
> > +$dtrace $dt_flags -c ./main -qs D.d >& actual.txt
> > +if [ $? -ne 0 ]; then
> > +	echo ERROR: dtrace error
> > +	echo "==== D script"
> > +	cat D.d
> > +	echo "==== output"
> > +	cat actual.txt
> > +	exit 1
> > +fi
> > +
> > +# Check results.
> > +
> > +if diff -q expect.txt actual.txt; then
> > +	echo success
> > +	exit 0
> > +else
> > +	echo ERROR: unexpected results
> > +	echo "==== expect"
> > +	cat expect.txt
> > +	echo "==== actual"
> > +	cat actual.txt
> > +	echo "==== diff"
> > +	diff expect.txt actual.txt
> > +	exit 1
> > +fi
> > -- 
> > 2.43.5
> > 
> 
> _______________________________________________
> DTrace-devel mailing list
> DTrace-devel at oss.oracle.com
> https://oss.oracle.com/mailman/listinfo/dtrace-devel



More information about the DTrace-devel mailing list