[DTrace-devel] [PATCH v2 2/2] usdt: is-enabled probe support

Kris Van Hees kris.van.hees at oracle.com
Thu May 18 05:03:54 UTC 2023


On Wed, May 17, 2023 at 08:50:22PM +0100, Nick Alcock via DTrace-devel wrote:
> This implementation is in many ways similar to v1's, but contains one
> significant simplification: rather than is-enabled probes appearing to
> the user as a function that returns a 1 or 0, they appear as a function
> that returns void and takes the address of a local variable: the
> _IS_ENABLED macros use the GCC statement-expression extension
> to declare and initialize a distinct local for each use of the
> is-enabled probe:
> 
> 	({ uint32_t enabled = 0; \
> 	__dtraceenabled_foo___bar(&enabled); \
> 	   enabled; })
> 
> The is-enabled trampoline writes a 1 into this local variable.  This
> allows the dt_link code to discard all the architecture-dependent code
> dealing with return value handling and treat is-enabled probes just like
> other USDT probes: it still tracks whether is-enabled probes are used,
> but doesn't use the info for anything but setting the DOF version.
> 
> The downside of this approach, of course, is that users need the
> statement-expression extension to work, and that old is-enabled probes
> from DTrace v1 aren't going to work without regeneration with dtrace
> -G. Neither of these seem likely to be serious problems in practice, and
> the commit before this one should help.
> 
> We use #pragma system_header to suppress -pedantic warnings about
> use of the extension.
> 
> Internally, there are tiny changes in the dtprobed and dt_pid
> uprobe-registration-and-creation layers to put is-enabled probes in a
> different uprobe group to prevent their names clashing with USDT probes
> with the same name (dt_pid_is_enabled/ rather than dt_pid/). Normal USDT
> probes enable the correspondinng is-enabled probe, if any, when they are
> enabled: those probes have custom trampoline that copy a 64-bit-wide 1
> into the first function parameter (and have truncated parameter-copying
> code that avoids preserving any parameter but the first, because there
> will never be any more).
> 
> Please ignore the code duplication between trampoline() and
> trampoline_is_enabled(): this is temporary to make it easier to make
> changes for getting globbed systemwide probing working later on.
> 
> Signed-off-by: Nick Alcock <nick.alcock at oracle.com>

Reviewed-by: Kris Van Hees <kris.van.hees at oracle.com>

... with little changes below...

> ---
>  dtprobed/dtprobed.c                    |   8 +-
>  libcommon/uprobes.c                    |  27 ++--
>  libcommon/uprobes.h                    |  22 +--
>  libdtrace/dt_link.c                    | 188 +++++++--------------
>  libdtrace/dt_pid.c                     |  31 ++--
>  libdtrace/dt_program.c                 |  28 ++--
>  libdtrace/dt_prov_fbt.c                |   2 +-
>  libdtrace/dt_prov_uprobe.c             | 215 ++++++++++++++++++++++---
>  test/unittest/usdt/tst.enable.d        |   3 +-
>  test/unittest/usdt/tst.enable_and.d    |   3 +-
>  test/unittest/usdt/tst.enable_and_2.d  |   3 +-
>  test/unittest/usdt/tst.enable_or_2.d   |   3 +-
>  test/unittest/usdt/tst.enable_return.d |   3 +-
>  test/unittest/usdt/tst.enable_stmt.d   |   3 +-
>  test/unittest/usdt/tst.enabled.sh      |   3 +-
>  15 files changed, 324 insertions(+), 218 deletions(-)
> 
> diff --git a/dtprobed/dtprobed.c b/dtprobed/dtprobed.c
> index af647d92d3355..3725dba2fe1c6 100644
> --- a/dtprobed/dtprobed.c
> +++ b/dtprobed/dtprobed.c
> @@ -1,6 +1,6 @@
>  /*
>   * Oracle Linux DTrace; DOF-consumption and USDT-probe-creation daemon.
> - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2022, 2023, 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.
>   */
> @@ -323,15 +323,13 @@ create_probe(pid_t pid, dof_parsed_t *provider, dof_parsed_t *probe,
>  {
>  	const char *mod, *fun, *prb;
>  
> -	if (tp->tracepoint.is_enabled)
> -		return;				/* Not yet implemented.  */
> -
>  	mod = probe->probe.name;
>  	fun = mod + strlen(mod) + 1;
>  	prb = fun + strlen(fun) + 1;
>  
>  	free(uprobe_create_from_addr(pid, tp->tracepoint.addr,
> -		provider->provider.name, mod, fun, prb));
> +		tp->tracepoint.is_enabled, provider->provider.name,
> +		mod, fun, prb));
>  }
>  
>  /*
> diff --git a/libcommon/uprobes.c b/libcommon/uprobes.c
> index 8a45a1f2a2b9c..8c3cc6280e9a1 100644
> --- a/libcommon/uprobes.c
> +++ b/libcommon/uprobes.c
> @@ -1,6 +1,6 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2019, 2023, 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.
>   */
> @@ -209,13 +209,13 @@ uprobe_decode_name(const char *name)
>  }
>  
>  char *
> -uprobe_name(dev_t dev, ino_t ino, uint64_t addr, int isret)
> +uprobe_name(dev_t dev, ino_t ino, uint64_t addr, int isret, int is_enabled)
>  {
>  	char	*name;
>  
> -	if (asprintf(&name, "dt_pid/%c_%llx_%llx_%lx", isret ? 'r' : 'p',
> -		     (unsigned long long)dev, (unsigned long long)ino,
> -		     (unsigned long)addr) < 0)
> +	if (asprintf(&name, "dt_pid%s/%c_%llx_%llx_%lx", is_enabled?"_is_enabled":"",
> +		     isret ? 'r' : 'p', (unsigned long long)dev,
> +		     (unsigned long long)ino, (unsigned long)addr) < 0)
>  		return NULL;
>  
>  	return name;
> @@ -229,7 +229,7 @@ uprobe_name(dev_t dev, ino_t ino, uint64_t addr, int isret)
>   */
>  char *
>  uprobe_create_named(dev_t dev, ino_t ino, uint64_t addr, const char *spec, int isret,
> -		    const char *prv, const char *mod, const char *fun,
> +		    int is_enabled, const char *prv, const char *mod, const char *fun,
>  		    const char *prb)
>  {
>  	int	fd = -1;
> @@ -261,7 +261,7 @@ uprobe_create_named(dev_t dev, ino_t ino, uint64_t addr, const char *spec, int i
>  			return NULL;
>  	}
>  
> -	name = uprobe_name(dev, ino, addr, isret);
> +	name = uprobe_name(dev, ino, addr, isret, is_enabled);
>  	if (!name)
>  		goto out;
>  
> @@ -292,9 +292,10 @@ out:
>   * systemwide uprobe list.)
>   */
>  char *
> -uprobe_create(dev_t dev, ino_t ino, uint64_t addr, const char *spec, int isret)
> +uprobe_create(dev_t dev, ino_t ino, uint64_t addr, const char *spec, int isret,
> +	int is_enabled)
>  {
> -	return uprobe_create_named(dev, ino, addr, spec, isret,
> +	return uprobe_create_named(dev, ino, addr, spec, isret, is_enabled,
>  				   NULL, NULL, NULL, NULL);
>  }
>  
> @@ -304,7 +305,7 @@ uprobe_create(dev_t dev, ino_t ino, uint64_t addr, const char *spec, int isret)
>   * are set, they are passed down as the name of the corresponding DTrace probe.
>   */
>  char *
> -uprobe_create_from_addr(pid_t pid, uint64_t addr, const char *prv,
> +uprobe_create_from_addr(pid_t pid, uint64_t addr, int is_enabled, const char *prv,
>  			const char *mod, const char *fun, const char *prb)
>  {
>  	char *spec;
> @@ -316,7 +317,7 @@ uprobe_create_from_addr(pid_t pid, uint64_t addr, const char *prv,
>  		return NULL;
>  
>  	name = uprobe_create_named(mapp.pr_dev, mapp.pr_inum, addr, spec, 0,
> -				   prv, mod, fun, prb);
> +				   is_enabled, prv, mod, fun, prb);
>  	free(spec);
>  	return name;
>  }
> @@ -325,13 +326,13 @@ uprobe_create_from_addr(pid_t pid, uint64_t addr, const char *prv,
>   * Destroy a uprobe for a given device, address, and spec.
>   */
>  int
> -uprobe_delete(dev_t dev, ino_t ino, uint64_t addr, int isret)
> +uprobe_delete(dev_t dev, ino_t ino, uint64_t addr, int isret, int is_enabled)
>  {
>  	int	fd = -1;
>  	int	rc = -1;
>  	char	*name;
>  
> -	name = uprobe_name(dev, ino, addr, isret);
> +	name = uprobe_name(dev, ino, addr, isret, is_enabled);
>  	if (!name)
>  		goto out;
>  
> diff --git a/libcommon/uprobes.h b/libcommon/uprobes.h
> index fde6ba40235a2..bd5f79d1cc9b9 100644
> --- a/libcommon/uprobes.h
> +++ b/libcommon/uprobes.h
> @@ -1,6 +1,6 @@
>  /*
>   * Oracle Linux DTrace; simple uprobe helper functions
> - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2022, 2023, 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.
>   */
> @@ -15,17 +15,19 @@
>  
>  extern char *uprobe_spec_by_addr(pid_t pid, ps_prochandle *P, uint64_t addr,
>  				 prmap_t *mapp);
> -extern char *uprobe_name(dev_t dev, ino_t ino, uint64_t addr, int isret);
> +extern char *uprobe_name(dev_t dev, ino_t ino, uint64_t addr, int isret,
> +			 int is_enabled);
>  extern char *uprobe_create_named(dev_t dev, ino_t ino, uint64_t addr,
> -				 const char *spec, int isret, const char *prv,
> -				 const char *mod, const char *fun,
> -				 const char *prb);
> +				 const char *spec, int isret, int is_enabled,
> +				 const char *prv, const char *mod,
> +				 const char *fun, const char *prb);
>  extern char *uprobe_create(dev_t dev, ino_t ino, uint64_t addr, const char *spec,
> -			   int isret);
> -extern char *uprobe_create_from_addr(pid_t pid, uint64_t addr, const char *prv,
> -				     const char *mod, const char *fun,
> -				     const char *prb);
> -extern int uprobe_delete(dev_t dev, ino_t ino, uint64_t addr, int isret);
> +			   int isret, int is_enabled);
> +extern char *uprobe_create_from_addr(pid_t pid, uint64_t addr, int is_enabled,
> +				     const char *prv, const char *mod,
> +				     const char *fun, const char *prb);
> +extern int uprobe_delete(dev_t dev, ino_t ino, uint64_t addr, int isret,
> +			 int is_enabled);
>  extern char *uprobe_encode_name(const char *);
>  extern char *uprobe_decode_name(const char *);
>  
> diff --git a/libdtrace/dt_link.c b/libdtrace/dt_link.c
> index 2c7ac03ca1ee2..3346720fcf62e 100644
> --- a/libdtrace/dt_link.c
> +++ b/libdtrace/dt_link.c
> @@ -1,6 +1,6 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2008, 2023, 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.
>   */
> @@ -775,8 +775,7 @@ dt_elf_symtab_lookup(Elf_Data *data_sym, int nsym, uintptr_t addr, uint_t shn,
>  
>  /*ARGSUSED*/
>  static int
> -dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
> -    uint32_t *off)
> +dt_modtext(dtrace_hdl_t *dtp, char *p, GElf_Rela *rela, uint32_t *off)
>  {
>  	uint32_t *ip;
>  
> @@ -801,25 +800,18 @@ dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
>  	 * invocation. Check to see if the present instruction sequence matches
>  	 * the one we would install below.
>  	 */
> -	if (isenabled) {
> -		if (ip[0] == DT_OP_NOP) {
> +	if (DT_IS_RESTORE(ip[1])) {
> +		if (ip[0] == DT_OP_RET) {
>  			(*off) += sizeof(ip[0]);
>  			return 0;
>  		}
> +	} else if (DT_IS_MOV_O7(ip[1])) {
> +		if (DT_IS_RETL(ip[0]))
> +			return 0;
>  	} else {
> -		if (DT_IS_RESTORE(ip[1])) {
> -			if (ip[0] == DT_OP_RET) {
> -				(*off) += sizeof(ip[0]);
> -				return 0;
> -			}
> -		} else if (DT_IS_MOV_O7(ip[1])) {
> -			if (DT_IS_RETL(ip[0]))
> -				return 0;
> -		} else {
> -			if (ip[0] == DT_OP_NOP) {
> -				(*off) += sizeof(ip[0]);
> -				return 0;
> -			}
> +		if (ip[0] == DT_OP_NOP) {
> +			(*off) += sizeof(ip[0]);
> +			return 0;
>  		}
>  	}
>  
> @@ -832,58 +824,32 @@ dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
>  		return -1;
>  	}
>  
> -	if (isenabled) {
> -		/*
> -		 * It would necessarily indicate incorrect usage if an is-
> -		 * enabled probe were tail-called so flag that as an error.
> -		 * It's also potentially (very) tricky to handle gracefully,
> -		 * but could be done if this were a desired use scenario.
> -		 */
> -		if (DT_IS_RESTORE(ip[1]) || DT_IS_MOV_O7(ip[1])) {
> -			dt_dprintf("tail call to is-enabled probe at %llx\n",
> -			    (unsigned long long)rela->r_offset);
> -			return -1;
> -		}
> -
> -
> -		/*
> -		 * On SPARC, we take advantage of the fact that the first
> -		 * argument shares the same register as for the return value.
> -		 * The macro handles the work of zeroing that register so we
> -		 * don't need to do anything special here. We instrument the
> -		 * instruction in the delay slot as we'll need to modify the
> -		 * return register after that instruction has been emulated.
> -		 */
> -		ip[0] = DT_OP_NOP;
> +	/*
> +	 * If the call is followed by a restore, it's a tail call so
> +	 * change the call to a ret. If the call if followed by a mov
> +	 * of a register into %o7, it's a tail call in leaf context
> +	 * so change the call to a retl-like instruction that returns
> +	 * to that register value + 8 (rather than the typical %o7 +
> +	 * 8); the delay slot instruction is left, but should have no
> +	 * effect. Otherwise we change the call to be a nop. We
> +	 * identify the subsequent instruction as the probe point in
> +	 * all but the leaf tail-call case to ensure that arguments to
> +	 * the probe are complete and consistent. An astute, though
> +	 * largely hypothetical, observer would note that there is the
> +	 * possibility of a false-positive probe firing if the function
> +	 * contained a branch to the instruction in the delay slot of
> +	 * the call. Fixing this would require significant in-kernel
> +	 * modifications, and isn't worth doing until we see it in the
> +	 * wild.
> +	 */
> +	if (DT_IS_RESTORE(ip[1])) {
> +		ip[0] = DT_OP_RET;
>  		(*off) += sizeof(ip[0]);
> +	} else if (DT_IS_MOV_O7(ip[1])) {
> +		ip[0] = DT_MAKE_RETL(DT_RS2(ip[1]));
>  	} else {
> -		/*
> -		 * If the call is followed by a restore, it's a tail call so
> -		 * change the call to a ret. If the call if followed by a mov
> -		 * of a register into %o7, it's a tail call in leaf context
> -		 * so change the call to a retl-like instruction that returns
> -		 * to that register value + 8 (rather than the typical %o7 +
> -		 * 8); the delay slot instruction is left, but should have no
> -		 * effect. Otherwise we change the call to be a nop. We
> -		 * identify the subsequent instruction as the probe point in
> -		 * all but the leaf tail-call case to ensure that arguments to
> -		 * the probe are complete and consistent. An astute, though
> -		 * largely hypothetical, observer would note that there is the
> -		 * possibility of a false-positive probe firing if the function
> -		 * contained a branch to the instruction in the delay slot of
> -		 * the call. Fixing this would require significant in-kernel
> -		 * modifications, and isn't worth doing until we see it in the
> -		 * wild.
> -		 */
> -		if (DT_IS_RESTORE(ip[1])) {
> -			ip[0] = DT_OP_RET;
> -			(*off) += sizeof(ip[0]);
> -		} else if (DT_IS_MOV_O7(ip[1])) {
> -			ip[0] = DT_MAKE_RETL(DT_RS2(ip[1]));
> -		} else {
> -			ip[0] = DT_OP_NOP;
> -			(*off) += sizeof(ip[0]);
> -		}
> +		ip[0] = DT_OP_NOP;
> +		(*off) += sizeof(ip[0]);
>  	}
>  
>  	return 0;
> @@ -895,13 +861,9 @@ dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
>  #define	DT_OP_RET		0xc3
>  #define	DT_OP_CALL		0xe8
>  #define	DT_OP_JMP32		0xe9
> -#define	DT_OP_REX_RAX		0x48
> -#define	DT_OP_XOR_EAX_0		0x33
> -#define	DT_OP_XOR_EAX_1		0xc0
>  
>  static int
> -dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
> -    uint32_t *off)
> +dt_modtext(dtrace_hdl_t *dtp, char *p, GElf_Rela *rela, uint32_t *off)
>  {
>  	uint8_t *ip = (uint8_t *)(p + rela->r_offset - 1);
>  	uint8_t ret;
> @@ -924,37 +886,20 @@ dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
>  	 */
>  	if (GELF_R_TYPE(rela->r_info) != R_386_PC32 &&
>  	    GELF_R_TYPE(rela->r_info) != R_386_PLT32 &&
> -	    GELF_R_TYPE(rela->r_info) != R_386_NONE)
> +	    GELF_R_TYPE(rela->r_info) != R_386_NONE) {
> +		dt_dprintf("unexpected reloc type %li\n", GELF_R_TYPE(rela->r_info));
>  		return -1;
> +	}
>  
>  	/*
>  	 * We may have already processed this object file in an earlier linker
>  	 * invocation. Check to see if the present instruction sequence matches
> -	 * the one we would install. For is-enabled probes, we advance the
> -	 * offset to the first nop instruction in the sequence to match the
> -	 * text modification code below.
> +	 * the one we would install.
>  	 */
> -	if (!isenabled) {
> -		if ((ip[0] == DT_OP_NOP || ip[0] == DT_OP_RET) &&
> -		    ip[1] == DT_OP_NOP && ip[2] == DT_OP_NOP &&
> -		    ip[3] == DT_OP_NOP && ip[4] == DT_OP_NOP)
> -			return 0;
> -	} else if (dtp->dt_oflags & DTRACE_O_ILP32) {
> -		if (ip[0] == DT_OP_XOR_EAX_0 && ip[1] == DT_OP_XOR_EAX_1 &&
> -		    (ip[2] == DT_OP_NOP || ip[2] == DT_OP_RET) &&
> -		    ip[3] == DT_OP_NOP && ip[4] == DT_OP_NOP) {
> -			(*off) += 2;
> -			return 0;
> -		}
> -	} else {
> -		if (ip[0] == DT_OP_REX_RAX &&
> -		    ip[1] == DT_OP_XOR_EAX_0 && ip[2] == DT_OP_XOR_EAX_1 &&
> -		    (ip[3] == DT_OP_NOP || ip[3] == DT_OP_RET) &&
> -		    ip[4] == DT_OP_NOP) {
> -			(*off) += 3;
> -			return 0;
> -		}
> -	}
> +	if ((ip[0] == DT_OP_NOP || ip[0] == DT_OP_RET) &&
> +	    ip[1] == DT_OP_NOP && ip[2] == DT_OP_NOP &&
> +	    ip[3] == DT_OP_NOP && ip[4] == DT_OP_NOP)
> +		return 0;
>  
>  	/*
>  	 * We expect either a call instrution with a 32-bit displacement or a
> @@ -969,33 +914,13 @@ dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
>  	ret = (ip[0] == DT_OP_JMP32) ? DT_OP_RET : DT_OP_NOP;
>  
>  	/*
> -	 * Establish the instruction sequence -- all nops for probes, and an
> -	 * instruction to clear the return value register (%eax/%rax) followed
> -	 * by nops for is-enabled probes. For is-enabled probes, we advance
> -	 * the offset to the first nop. This isn't stricly necessary but makes
> -	 * for more readable disassembly when the probe is enabled.
> +	 * Establish the instruction sequence: all nops.
>  	 */
> -	if (!isenabled) {
> -		ip[0] = ret;
> -		ip[1] = DT_OP_NOP;
> -		ip[2] = DT_OP_NOP;
> -		ip[3] = DT_OP_NOP;
> -		ip[4] = DT_OP_NOP;
> -	} else if (dtp->dt_oflags & DTRACE_O_ILP32) {
> -		ip[0] = DT_OP_XOR_EAX_0;
> -		ip[1] = DT_OP_XOR_EAX_1;
> -		ip[2] = ret;
> -		ip[3] = DT_OP_NOP;
> -		ip[4] = DT_OP_NOP;
> -		(*off) += 2;
> -	} else {
> -		ip[0] = DT_OP_REX_RAX;
> -		ip[1] = DT_OP_XOR_EAX_0;
> -		ip[2] = DT_OP_XOR_EAX_1;
> -		ip[3] = ret;
> -		ip[4] = DT_OP_NOP;
> -		(*off) += 3;
> -	}
> +	ip[0] = ret;
> +	ip[1] = DT_OP_NOP;
> +	ip[2] = DT_OP_NOP;
> +	ip[3] = DT_OP_NOP;
> +	ip[4] = DT_OP_NOP;
>  
>  	return 0;
>  }
> @@ -1008,8 +933,7 @@ dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
>  #define	DT_OP_JUMP26		0x14000000
>  
>  static int
> -dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
> -    uint32_t *off)
> +dt_modtext(dtrace_hdl_t *dtp, char *p, GElf_Rela *rela, uint32_t *off)
>  {
>  	uint32_t *ip;
>  
> @@ -1050,11 +974,9 @@ dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
>  	}
>  
>  	/*
> -	 * On arm64, we do not have to differentiate between regular probes and
> -	 * is-enabled probes.  Both cases are encoded as a regular branch for
> -	 * non-tail call locations, and a jump for tail call locations.  Calls
> -	 * are to be converted into a no-op whereas jumps should become a
> -	 * return.
> +	 * On arm64, we encode all probes as a regular branch for non-tail call
> +	 * locations, and a jump for tail call locations.  Calls are to be
> +	 * converted into a no-op whereas jumps should become a return.
>  	 */
>  	if (ip[0] == DT_OP_CALL26)
>  		ip[0] = DT_OP_NOP;
> @@ -1502,10 +1424,8 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
>  			assert(fsym.st_value <= rela.r_offset);
>  
>  			off = rela.r_offset - fsym.st_value;
> -			if (dt_modtext(dtp, data_tgt->d_buf, eprobe,
> -			    &rela, &off) != 0) {
> +			if (dt_modtext(dtp, data_tgt->d_buf, &rela, &off) != 0)
>  				goto err;
> -			}
>  
>  			if (dt_probe_define(pvp, prp, s, r, off, eprobe) != 0)
>  				return dt_link_error(dtp, elf, fd, bufs,
> diff --git a/libdtrace/dt_pid.c b/libdtrace/dt_pid.c
> index fd9e0d1da62dd..06bd7a4dd24aa 100644
> --- a/libdtrace/dt_pid.c
> +++ b/libdtrace/dt_pid.c
> @@ -1,6 +1,6 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2010, 2022, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2010, 2023, 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.
>   */
> @@ -626,6 +626,8 @@ dt_pid_create_usdt_probes(dtrace_hdl_t *dtp, dt_proc_t *dpr,
>  		dev_t dev;
>  		ino_t inum;
>  		uint64_t off;
> +		int is_enabled;
> +		const char *fmt;
>  		unsigned long long dev_ll, inum_ll;
>  		char *inum_str = NULL;
>  		char *spec = NULL;
> @@ -634,11 +636,23 @@ dt_pid_create_usdt_probes(dtrace_hdl_t *dtp, dt_proc_t *dpr,
>  		pid_probespec_t psp;
>  
>  #define UPROBE_PREFIX "p:dt_pid/p_"
> -		if (strncmp(buf, UPROBE_PREFIX, strlen(UPROBE_PREFIX)) != 0)
> +#define UPROBE_IS_ENABLED_PREFIX "p:dt_pid_is_enabled/p_"
> +#define UPROBE_PROBE_FMT "%llx_%llx_%lx %ms P%m[^= ]=\\1 M%m[^= ]=\\2 F%m[^= ]=\\3 N%m[^= ]=\\4"
> +#define UPROBE_FMT UPROBE_PREFIX UPROBE_PROBE_FMT
> +#define UPROBE_IS_ENABLED_FMT UPROBE_IS_ENABLED_PREFIX UPROBE_PROBE_FMT
> +
> +		if (strncmp(buf, UPROBE_PREFIX, strlen(UPROBE_PREFIX)) == 0) {
> +			is_enabled = 0;
> +			fmt = UPROBE_FMT;
> +		} else if (strncmp(buf, UPROBE_IS_ENABLED_PREFIX,
> +			strlen(UPROBE_IS_ENABLED_PREFIX)) == 0) {
> +			is_enabled = 1;
> +			fmt = UPROBE_IS_ENABLED_FMT;
> +		}
> +		else /* Not a DTrace uprobe. */

Two lines above should be combined as:
		} else /* Not a DTrace uprobe. */

>  			continue;
>  
> -		switch (sscanf(buf, "p:dt_pid/p_%llx_%llx_%lx %ms "
> -			       "P%m[^= ]=\\1 M%m[^= ]=\\2 F%m[^= ]=\\3 N%m[^= ]=\\4", &dev_ll, &inum_ll,
> +		switch (sscanf(buf, fmt, &dev_ll, &inum_ll,
>  			       &off, &spec, &eprv, &emod, &efun, &eprb)) {
>  		case 8: /* Includes dtrace probe names: decode them. */
>  			prv = uprobe_decode_name(eprv);
> @@ -664,9 +678,7 @@ dt_pid_create_usdt_probes(dtrace_hdl_t *dtp, dt_proc_t *dpr,
>  		 * Make the underlying probe, if not already present.
>  		 */
>  		memset(&psp, 0, sizeof(pid_probespec_t));
> -
> -		/* FIXME: DTPPT_IS_ENABLED needs to be supported also.  */
> -		psp.pps_type = DTPPT_OFFSETS;
> +		psp.pps_type = is_enabled ? DTPPT_IS_ENABLED : DTPPT_OFFSETS;
>  
>  		/*
>  		 * These components are only used for creation of an underlying
> @@ -732,8 +744,9 @@ dt_pid_create_usdt_probes(dtrace_hdl_t *dtp, dt_proc_t *dpr,
>  
>  		if (pvp->impl->provide_probe(dtp, &psp) < 0 && pdp) {
>  			dt_pid_error(dtp, pcb, dpr, D_PROC_USDT,
> -				     "failed to instantiate probe %s for pid %d: %s",
> -				     pdp->prb, dpr->dpr_pid,
> +				     "failed to instantiate %sprobe %s for pid %d: %s",
> +				     is_enabled ? "is-enabled ": "", pdp->prb,
> +				     dpr->dpr_pid,
>  				     dtrace_errmsg(dtp, dtrace_errno(dtp)));
>  			ret = -1;
>  		}
> diff --git a/libdtrace/dt_program.c b/libdtrace/dt_program.c
> index a95d0eefdb1a2..a4b052fc47603 100644
> --- a/libdtrace/dt_program.c
> +++ b/libdtrace/dt_program.c
> @@ -1,6 +1,6 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2009, 2021, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2009, 2023, 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.
>   */
> @@ -368,12 +368,8 @@ dt_header_decl(dt_idhash_t *dhp, dt_ident_t *idp, void *data)
>  		return dt_set_errno(dtp, errno);
>  
>  	if (fprintf(infop->dthi_out,
> -	    "#if !defined(__aarch64__) && !defined(__sparc)\n"
> -	    "extern int __dtraceenabled_%s___%s(void);\n"
> -	    "#else\n"
> -	    "extern int __dtraceenabled_%s___%s(long);\n"
> -	    "#endif\n",
> -	    infop->dthi_pfname, fname, infop->dthi_pfname, fname) < 0)
> +	    "extern void __dtraceenabled_%s___%s(uint32_t *flag);\n",
> +	    infop->dthi_pfname, fname) < 0)
>  		return dt_set_errno(dtp, errno);
>  
>  	return 0;
> @@ -436,17 +432,18 @@ dt_header_probe(dt_idhash_t *dhp, dt_ident_t *idp, void *data)
>  
>  	if (!infop->dthi_empty) {
>  		if (fprintf(infop->dthi_out,
> -		    "#if !defined(__aarch64__) && !defined(__sparc)\n"
> +		    "#ifdef __GNUC__\n"
>  		    "#define\t%s_%s_ENABLED() \\\n"
> -		    "\t__dtraceenabled_%s___%s()\n"
> +		    "\t({ uint32_t enabled = 0; \\\n"
> +		    "\t__dtraceenabled_%s___%s(&enabled); \\\n"
> +		    "\t   enabled; })\n"
>  		    "#else\n"
> -		    "#define\t%s_%s_ENABLED() \\\n"
> -		    "\t__dtraceenabled_%s___%s(0)\n"
> +		    "#define\t%s_%s_ENABLED() (1)\\n"
> +		    "#endif\n"
>  		    "#endif\n",
>  		    infop->dthi_pmname, mname,
>  		    infop->dthi_pfname, fname,
> -		    infop->dthi_pmname, mname,
> -		    infop->dthi_pfname, fname) < 0)
> +		    infop->dthi_pmname, mname) < 0)
>  			return dt_set_errno(dtp, errno);
>  
>  	} else {
> @@ -536,6 +533,11 @@ dtrace_program_header(dtrace_hdl_t *dtp, FILE *out, const char *fname)
>  	if (fprintf(out, "#ifdef\t__cplusplus\nextern \"C\" {\n#endif\n\n") < 0)
>  		return -1;
>  
> +	if (fprintf(out, "#ifdef\t__GNUC__\n"
> +		"#pragma GCC system_header\n"
> +		"#endif\n\n") < 0)
> +		return -1;
> +
>  	while ((pvp = dt_htab_next(dtp->dt_provs, &it)) != NULL) {
>  		if (dt_header_provider(dtp, pvp, out) != 0) {
>  			dt_htab_next_destroy(it);
> diff --git a/libdtrace/dt_prov_fbt.c b/libdtrace/dt_prov_fbt.c
> index add76c55f3ae8..ee848b453e9af 100644
> --- a/libdtrace/dt_prov_fbt.c
> +++ b/libdtrace/dt_prov_fbt.c
> @@ -1,6 +1,6 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2019, 2023, 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.
>   *
> diff --git a/libdtrace/dt_prov_uprobe.c b/libdtrace/dt_prov_uprobe.c
> index f85d15297e910..32b6996762b3f 100644
> --- a/libdtrace/dt_prov_uprobe.c
> +++ b/libdtrace/dt_prov_uprobe.c
> @@ -1,6 +1,6 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2021, 2023, 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.
>   *
> @@ -23,13 +23,15 @@
>  #include "uprobes.h"
>  
>  /* Provider name for the underlying probes. */
> -static const char		prvname[] = "uprobe";
> +static const char	prvname[] = "uprobe";
> +static const char	prvname_is_enabled[] = "uprobe__is_enabled";
>  
> -#define UPROBE_EVENTS		TRACEFS "uprobe_events"
> +#define UPROBE_EVENTS	TRACEFS "uprobe_events"
>  
>  #define PP_IS_MINE	1
>  #define PP_IS_RETURN	2
>  #define PP_IS_FUNCALL	4
> +#define PP_IS_ENABLED	8
>  
>  typedef struct dt_uprobe {
>  	dev_t		dev;
> @@ -54,12 +56,15 @@ static const dtrace_pattr_t	pattr = {
>  { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
>  };
>  
> +dt_provimpl_t	dt_uprobe_is_enabled;
>  dt_provimpl_t	dt_pid;
>  dt_provimpl_t	dt_usdt;
>  
>  static int populate(dtrace_hdl_t *dtp)
>  {
>  	dt_provider_create(dtp, dt_uprobe.name, &dt_uprobe, &pattr);
> +	dt_provider_create(dtp, dt_uprobe_is_enabled.name,
> +			   &dt_uprobe_is_enabled, &pattr);
>  	dt_provider_create(dtp, dt_pid.name, &dt_pid, &pattr);
>  	dt_provider_create(dtp, dt_usdt.name, &dt_usdt, &pattr);
>  
> @@ -115,6 +120,7 @@ static dt_probe_t *create_underlying(dtrace_hdl_t *dtp,
>  	dtrace_probedesc_t	pd;
>  	dt_probe_t		*prp;
>  	dt_uprobe_t		*upp;
> +	int			is_enabled = 0;
>  
>  	/*
>  	 * The underlying probes (uprobes) represent the tracepoints that pid
> @@ -136,6 +142,9 @@ static dt_probe_t *create_underlying(dtrace_hdl_t *dtp,
>  	case DTPPT_RETURN:
>  		strcpy(prb, "return");
>  		break;
> +	case DTPPT_IS_ENABLED:
> +		is_enabled = 1;
> +		/* Fallthrough. */
>  	case DTPPT_ENTRY:
>  	case DTPPT_OFFSETS:
>  		snprintf(prb, sizeof(prb), "%lx", psp->pps_off);
> @@ -146,7 +155,7 @@ static dt_probe_t *create_underlying(dtrace_hdl_t *dtp,
>  	}
>  
>  	pd.id = DTRACE_IDNONE;
> -	pd.prv = prvname;
> +	pd.prv = is_enabled ? prvname_is_enabled : prvname;
>  	pd.mod = mod;
>  	pd.fun = psp->pps_fun;
>  	pd.prb = prb;
> @@ -156,7 +165,7 @@ static dt_probe_t *create_underlying(dtrace_hdl_t *dtp,
>  		dt_provider_t	*pvp;
>  
>  		/* Get the provider for underlying probes. */
> -		pvp = dt_provider_lookup(dtp, prvname);
> +		pvp = dt_provider_lookup(dtp, pd.prv);
>  		if (pvp == NULL)
>  			return NULL;
>  
> @@ -181,8 +190,18 @@ static dt_probe_t *create_underlying(dtrace_hdl_t *dtp,
>  	} else
>  		upp = prp->prv_data;
>  
> -	if (psp->pps_type == DTPPT_RETURN)
> -		upp->flags |= PP_IS_RETURN;
> +	switch (psp->pps_type) {
> +	case DTPPT_RETURN:
> +	    upp->flags |= PP_IS_RETURN;
> +	    break;
> +	case DTPPT_IS_ENABLED:
> +	    upp->flags |= PP_IS_ENABLED;
> +	    break;
> +	default: ;
> +	    /*
> +	     * No flags needed for other types.
> +	     */
> +	}
>  
>  	return prp;
>  
> @@ -302,7 +321,8 @@ static int provide_pid_probe(dtrace_hdl_t *dtp, const pid_probespec_t *psp)
>  
>  static int provide_usdt_probe(dtrace_hdl_t *dtp, const pid_probespec_t *psp)
>  {
> -	if (psp->pps_type != DTPPT_OFFSETS) {
> +	if (psp->pps_type != DTPPT_OFFSETS &&
> +	    psp->pps_type != DTPPT_IS_ENABLED) {
>  		dt_dprintf("pid: unknown USDT probe type %i\n", psp->pps_type);
>  		return -1;
>  	}
> @@ -310,7 +330,7 @@ static int provide_usdt_probe(dtrace_hdl_t *dtp, const pid_probespec_t *psp)
>  	return provide_probe(dtp, psp, psp->pps_prb, &dt_usdt, PP_IS_FUNCALL);
>  }
>  
> -static void enable(dtrace_hdl_t *dtp, dt_probe_t *prp)
> +static void enable(dtrace_hdl_t *dtp, dt_probe_t *prp, int is_usdt)
>  {
>  	const list_probe_t	*pup;
>  
> @@ -318,12 +338,26 @@ static void enable(dtrace_hdl_t *dtp, dt_probe_t *prp)
>  
>  	/*
>  	 * We need to enable the underlying probes (if not enabled yet).
> +	 *
> +	 * If necessary, we need to enable is-enabled probes too (if they
> +	 * exist).
>  	 */
>  	for (pup = prp->prv_data; pup != NULL; pup = dt_list_next(pup)) {
>  		dt_probe_t *uprp = pup->probe;
>  		dt_probe_enable(dtp, uprp);
>  	}
>  
> +	if (is_usdt) {
> +		dtrace_probedesc_t pd;
> +		dt_probe_t *iep;
> +
> +		memcpy(&pd, &prp->desc, sizeof(pd));
> +		pd.prv = prvname_is_enabled;
> +		iep = dt_probe_lookup(dtp, &pd);
> +		if (iep != NULL)
> +			dt_probe_enable(dtp, iep);
> +	}
> +
>  	/*
>  	 * Finally, ensure we're in the list of enablings as well.
>  	 * (This ensures that, among other things, the probes map
> @@ -333,13 +367,26 @@ static void enable(dtrace_hdl_t *dtp, dt_probe_t *prp)
>  		dt_list_append(&dtp->dt_enablings, prp);
>  }
>  
> +static void enable_pid(dtrace_hdl_t *dtp, dt_probe_t *prp)
> +{
> +	enable(dtp, prp, 0);
> +}
> +
> +/*
> + * USDT enabling has to enable any is-enabled probes as well.
> + */
> +static void enable_usdt(dtrace_hdl_t *dtp, dt_probe_t *prp)
> +{
> +	enable(dtp, prp, 1);
> +}
> +
>  /*
> - * Generate a BPF trampoline for a pid probe.
> + * Generate a BPF trampoline for a pid or USDT probe.
>   *
> - * The trampoline function is called when a pid probe triggers, and it must
> - * satisfy the following prototype:
> + * The trampoline function is called when one of these probes triggers, and it
> + * must satisfy the following prototype:
>   *
> - *	int dt_pid(dt_pt_regs *regs)
> + *	int dt_uprobe(dt_pt_regs *regs)
>   *
>   * The trampoline will first populate a dt_dctx_t struct.  It will then emulate
>   * the firing of all dependent pid* probes and their clauses.
> @@ -420,6 +467,120 @@ static void trampoline(dt_pcb_t *pcb, uint_t exitlbl)
>  	dt_cg_tramp_return(pcb);
>  }
>  
> +/*
> + * Copy the given immediate value into the address given by the specified probe
> + * argument.
> + */
> +static void
> +copyout_val(dt_pcb_t *pcb, uint_t lbl, uint32_t val, int arg)
> +{
> +	dt_regset_t	*drp = pcb->pcb_regs;
> +	dt_irlist_t	*dlp = &pcb->pcb_ir;
> +
> +	emitl(dlp, lbl, BPF_STORE_IMM(BPF_DW, BPF_REG_FP, DT_TRAMP_SP_SLOT(0),
> +		val));
> +
> +	if (dt_regset_xalloc_args(drp) == -1)
> +		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
> +	emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_1, BPF_REG_7, DMST_ARG(arg)));
> +	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)));
> +	emit(dlp, BPF_MOV_IMM(BPF_REG_3, sizeof(uint32_t)));
> +	dt_regset_xalloc(drp, BPF_REG_0);
> +	emit(dlp, BPF_CALL_HELPER(BPF_FUNC_probe_write_user));
> +
> +	/* XXX any point error-checking here? What can we possibly do? */
> +	dt_regset_free(drp, BPF_REG_0);
> +	dt_regset_free_args(drp);
> +}
> +
> +/*
> + * Generate a BPF trampoline for an is-enabled probe.  The is-enabled probe
> + * prototype looks like:
> + *
> + *	int is_enabled(int *arg)
> + *
> + * The trampoline dereferences the passed-in arg and writes 1 into it if this is
> + * one of the processes for which the probe is enabled.
> + */
> +static void trampoline_is_enabled(dt_pcb_t *pcb, uint_t exitlbl)
> +{
> +	dt_irlist_t		*dlp = &pcb->pcb_ir;
> +	const dt_probe_t	*prp = pcb->pcb_probe;
> +	const dt_uprobe_t	*upp = prp->prv_data;
> +	const list_probe_t	*pop;
> +	uint_t			lbl_assign = dt_irlist_label(dlp);
> +	uint_t			lbl_exit = pcb->pcb_exitlbl;
> +
> +	dt_cg_tramp_prologue(pcb);
> +
> +	/*
> +	 * After the dt_cg_tramp_prologue() call, we have:
> +	 *				//     (%r7 = dctx->mst)
> +	 *				//     (%r8 = dctx->ctx)
> +	 */
> +
> +	dt_cg_tramp_copy_regs(pcb);
> +
> +	/*
> +	 * Copy in the first function argument, a pointer value to which
> +	 * the is-enabled state of the probe will be written (necessarily
> +	 * 1 if this probe is running at all).
> +	 */
> +	emit(dlp,  BPF_LOAD(BPF_DW, BPF_REG_0, BPF_REG_8, PT_REGS_ARG0));
> +	emit(dlp,  BPF_STORE(BPF_DW, BPF_REG_7, DMST_ARG(0), BPF_REG_0));
> +
> +	/*
> +	 * Retrieve the PID of the process that caused the probe to fire.
> +	 */
> +	emit(dlp,  BPF_CALL_HELPER(BPF_FUNC_get_current_pid_tgid));
> +	emit(dlp,  BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32));
> +
> +	/*
> +	 * Generate a composite conditional clause, as above, except that rather
> +	 * than emitting call_clauses, we emit copyouts instead, using
> +	 * copyout_val() above:
> +	 *
> +	 *	if (pid == PID1) {
> +	 *		goto assign;
> +	 *	} else if (pid == PID2) {
> +	 *		goto assign;
> +	 *	} else if (pid == ...) {
> +	 *		goto assign;
> +	 *	}
> +	 *	goto exit;
> +	 *	assign:
> +	 *	    *arg0 = 1;
> +	 *	goto exit;
> +	 *
> +	 * It is valid and safe to use %r0 to hold the pid value because there
> +	 * are no assignments to %r0 possible in between the conditional
> +	 * statements.
> +	 */
> +	for (pop = dt_list_next(&upp->probes); pop != NULL;
> +	     pop = dt_list_next(pop)) {
> +		const dt_probe_t	*pprp = pop->probe;
> +		pid_t			pid;
> +		dt_ident_t		*idp;
> +
> +		pid = dt_pid_get_pid(pprp->desc, pcb->pcb_hdl, pcb, NULL);
> +		assert(pid != -1);
> +
> +		idp = dt_dlib_add_probe_var(pcb->pcb_hdl, pprp);
> +		assert(idp != NULL);
> +
> +		/*
> +		 * Check whether this pid-provider probe serves the current
> +		 * process, and copy out a 1 into arg 0 if so.
> +		 */
> +		emit(dlp,  BPF_BRANCH_IMM(BPF_JEQ, BPF_REG_0, pid, lbl_assign));
> +	}
> +	emit(dlp,  BPF_JUMP(lbl_exit));
> +	copyout_val(pcb, lbl_assign, 1, 0);
> +
> +	dt_cg_tramp_return(pcb);
> +}
> +
>  static int attach(dtrace_hdl_t *dtp, const dt_probe_t *prp, int bpf_fd)
>  {
>  	dt_uprobe_t	*upp = prp->prv_data;
> @@ -441,7 +602,7 @@ static int attach(dtrace_hdl_t *dtp, const dt_probe_t *prp, int bpf_fd)
>  			return -ENOENT;
>  
>  		prb = uprobe_create(upp->dev, upp->inum, upp->off, spec,
> -				    upp->flags & PP_IS_RETURN);
> +				    upp->flags & PP_IS_RETURN, 0);
>  		free(spec);
>  
>  		/*
> @@ -453,7 +614,8 @@ static int attach(dtrace_hdl_t *dtp, const dt_probe_t *prp, int bpf_fd)
>  
>  	if (prb == NULL)
>  		prb = uprobe_name(upp->dev, upp->inum, upp->off,
> -				  upp->flags & PP_IS_RETURN);
> +				  upp->flags & PP_IS_RETURN,
> +				  upp->flags & PP_IS_ENABLED);
>  
>  	/* open format file */
>  	rc = asprintf(&fn, "%s%s/format", EVENTSFS, prb);
> @@ -509,8 +671,9 @@ static void detach(dtrace_hdl_t *dtp, const dt_probe_t *prp)
>  	if (!(upp->flags & PP_IS_MINE))
>  		return;
>  
> -	uprobe_delete(upp->dev, upp->inum, upp->off, upp->flags & PP_IS_RETURN);
> -}
> +	uprobe_delete(upp->dev, upp->inum, upp->off, upp->flags & PP_IS_RETURN,
> +		      upp->flags & PP_IS_ENABLED);
> +	}
>  
>  /*
>   * Used for underlying probes (uprobes).
> @@ -526,6 +689,20 @@ dt_provimpl_t	dt_uprobe = {
>  	.probe_destroy	= &probe_destroy_underlying,
>  };
>  
> +/*
> + * Used for underlying is-enabled uprobes.
> + */
> +dt_provimpl_t	dt_uprobe_is_enabled = {
> +	.name		= prvname_is_enabled,
> +	.prog_type	= BPF_PROG_TYPE_KPROBE,
> +	.populate	= &populate,
> +	.trampoline	= &trampoline_is_enabled,
> +	.attach		= &attach,
> +	.probe_info	= &probe_info,
> +	.detach		= &detach,
> +	.probe_destroy	= &probe_destroy_underlying,
> +};
> +
>  /*
>   * Used for pid probes.
>   */
> @@ -533,7 +710,7 @@ dt_provimpl_t	dt_pid = {
>  	.name		= "pid",
>  	.prog_type	= BPF_PROG_TYPE_UNSPEC,
>  	.provide_probe	= &provide_pid_probe,
> -	.enable		= &enable,
> +	.enable		= &enable_pid,
>  	.probe_destroy	= &probe_destroy,
>  };
>  
> @@ -544,6 +721,6 @@ dt_provimpl_t	dt_usdt = {
>  	.name		= "usdt",
>  	.prog_type	= BPF_PROG_TYPE_UNSPEC,
>  	.provide_probe	= &provide_usdt_probe,
> -	.enable		= &enable,
> +	.enable		= &enable_usdt,
>  	.probe_destroy	= &probe_destroy,
>  };
> diff --git a/test/unittest/usdt/tst.enable.d b/test/unittest/usdt/tst.enable.d
> index 1211af97290ad..a95eee2009174 100644
> --- a/test/unittest/usdt/tst.enable.d
> +++ b/test/unittest/usdt/tst.enable.d
> @@ -1,11 +1,10 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2006, 2023, 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.
>   */
>  
> -/* @@xfail: dtv2, no is-enabled probes yet */
>  /* @@trigger: usdt-tst-special 2 */
>  
>  #pragma D option quiet
> diff --git a/test/unittest/usdt/tst.enable_and.d b/test/unittest/usdt/tst.enable_and.d
> index 94a053ef43bbb..9715c9c11eaa4 100644
> --- a/test/unittest/usdt/tst.enable_and.d
> +++ b/test/unittest/usdt/tst.enable_and.d
> @@ -1,11 +1,10 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2006, 2023, 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.
>   */
>  
> -/* @@xfail: dtv2, no is-enabled probes yet */
>  /* @@trigger: usdt-tst-special 5 */
>  
>  #pragma D option quiet
> diff --git a/test/unittest/usdt/tst.enable_and_2.d b/test/unittest/usdt/tst.enable_and_2.d
> index 3b2963f4330bc..47e8feb59825f 100644
> --- a/test/unittest/usdt/tst.enable_and_2.d
> +++ b/test/unittest/usdt/tst.enable_and_2.d
> @@ -1,11 +1,10 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2006, 2023, 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.
>   */
>  
> -/* @@xfail: dtv2, no is-enabled probes yet */
>  /* @@trigger: usdt-tst-special 6 */
>  
>  #pragma D option quiet
> diff --git a/test/unittest/usdt/tst.enable_or_2.d b/test/unittest/usdt/tst.enable_or_2.d
> index 6b599544fe9f4..c384cddfb8db4 100644
> --- a/test/unittest/usdt/tst.enable_or_2.d
> +++ b/test/unittest/usdt/tst.enable_or_2.d
> @@ -1,11 +1,10 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2006, 2023, 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.
>   */
>  
> -/* @@xfail: dtv2, no is-enabled probes yet */
>  /* @@trigger: usdt-tst-special 4 */
>  
>  #pragma D option quiet
> diff --git a/test/unittest/usdt/tst.enable_return.d b/test/unittest/usdt/tst.enable_return.d
> index 0d727b8a6d0c9..2e7b41f91c7b9 100644
> --- a/test/unittest/usdt/tst.enable_return.d
> +++ b/test/unittest/usdt/tst.enable_return.d
> @@ -1,11 +1,10 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2006, 2023, 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.
>   */
>  
> -/* @@xfail: dtv2, no is-enabled probes yet */
>  /* @@trigger: usdt-tst-special 8 */
>  
>  #pragma D option quiet
> diff --git a/test/unittest/usdt/tst.enable_stmt.d b/test/unittest/usdt/tst.enable_stmt.d
> index 5c26919f764d6..37e106bf6d1d1 100644
> --- a/test/unittest/usdt/tst.enable_stmt.d
> +++ b/test/unittest/usdt/tst.enable_stmt.d
> @@ -1,11 +1,10 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2006, 2023, 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.
>   */
>  
> -/* @@xfail: dtv2, no is-enabled probes yet */
>  /* @@trigger: usdt-tst-special 7 */
>  
>  #pragma D option quiet
> diff --git a/test/unittest/usdt/tst.enabled.sh b/test/unittest/usdt/tst.enabled.sh
> index 5363172fd8b4b..2c0a5b405e7a5 100755
> --- a/test/unittest/usdt/tst.enabled.sh
> +++ b/test/unittest/usdt/tst.enabled.sh
> @@ -1,7 +1,7 @@
>  #!/bin/bash
>  #
>  # Oracle Linux DTrace.
> -# Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
> +# Copyright (c) 2006, 2023, 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.
>  #
> @@ -9,7 +9,6 @@ if [ $# != 1 ]; then
>  	echo expected one argument: '<'dtrace-path'>'
>  	exit 2
>  fi
> -# @@xfail: dtv2, no is-enabled probes yet
>  
>  dtrace=$1
>  CC=/usr/bin/gcc
> -- 
> 2.39.1.268.g9de2f9a303
> 
> 
> _______________________________________________
> 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