[DTrace-devel] [PATCH 01/17] Revert "Remove drti.o and related support code."

Eugene Loh eugene.loh at oracle.com
Wed Aug 31 20:55:58 UTC 2022


This patch backs out the earlier patch as advertised.  Then I try:

     $ cat main.c
     int go(long long arg0, long long arg1, long long arg2, long long arg3,
            long long arg4, long long arg5, long long arg6, long long arg7,
            long long arg8, long long arg9) {
         return arg1;
     }
     int main(int argc, char **argv) {
         while (go(100, 111, 122, 133, 144, 155, 166, 177, 188, 199));
         return 0;
     }
     $ gcc main.c
     $ ./a.out &
     $ pid=$!

Next, I will try running:

     sudo ../build/run-dtrace -n '
     pid$1:a.out:go:entry
     {
         printf("args: %d %d %d %d %d %d %d %d %d %d\n", arg0, arg1,
             arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
         exit(0);
     }' $pid

If I use DTrace before this patch, I get:

     dtrace: description '
     pid$1:a.out:go:entry
     ' matched 1 probe
     CPU     ID                    FUNCTION:NAME
       1  92129                         go:entry args: 100 111 122 133 
144 155 166 177 188 199

which is good.

If I apply this patch, I get:

     dtrace: invalid probe specifier
     pid$1:a.out:go:entry
     {
         printf("args: %d %d %d %d %d %d %d %d %d %d\n", arg0, arg1,
             arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
         exit(0);
     }: dtrace-user/build/dlibs/drti.o: ELF machine type not supported

So if I jump to the end of the entire patch series, I get:

     dtrace: description '
     pid$1:a.out:go:entry
     ' matched 1 probe
     CPU     ID                    FUNCTION:NAME
       1  92129                         go:entry args: 100 111 122 133 
144 155 166 177 188 199

Again, that's good.  But it has only a single clause for the pid probe.  
What about with:

     sudo ../build/run-dtrace -n '
     pid$1:a.out:go:entry
     {
         printf("args: %d %d %d %d %d %d %d %d %d %d\n", arg0, arg1,
             arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
     }
     pid$1:a.out:go:entry
     {
         exit(0);
     }
     tick-5sec
     {
         printf("pid probe did not fire\n");
         exit(1);
     }' $pid

So I run with DTrace as it was before this patch:

     dtrace: description '
         pid$1:a.out:go:entry
         ' matched 3 probes
     CPU     ID                    FUNCTION:NAME
       1  92129                         go:entry args: 100 111 122 133 
144 155 166 177 188 199
       1  92129                         go:entry

That's good.  And with this patch?

     dtrace: invalid probe specifier
     pid$1:a.out:go:entry
     {
         printf("args: %d %d %d %d %d %d %d %d %d %d\n", arg0, arg1,
             arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
     }
     pid$1:a.out:go:entry
     {
         exit(0);
     }
     tick-5sec
     {
         printf("pid probe did not fire\n");
         exit(1);
     }: dtrace-user/build/dlibs/drti.o: ELF machine type not supported

Okay, that's no surprise.  What about if I jump to the end of the patch 
series?

     dtrace: description '
         pid$1:a.out:go:entry
         ' matched 3 probes
     CPU     ID                    FUNCTION:NAME
       3  92131                       :tick-5sec pid probe did not fire

That's bad.

So, to summarize:

*)  With this patch, the pid probe runs into the "drti.o ELF machine 
type" problem.

*)  If I jump to the end of the patch series, the first problem is 
resolved, but pid probes with multiple clauses do not fire.

On 8/10/22 18:06, Nick Alcock via DTrace-devel wrote:
> We're going to start using drti again, so bring it back.
>
> This reverts commit 1e45252a1e1c9a2ab35e03558dc4e5bbf63ad0d8.
> ---
>   Makefunctions       |   2 +-
>   libdtrace/Build     |  26 ++++++
>   libdtrace/drti-vers |   1 +
>   libdtrace/drti.c    | 193 ++++++++++++++++++++++++++++++++++++++++++++
>   libdtrace/dt_link.c |  22 +++--
>   5 files changed, 236 insertions(+), 8 deletions(-)
>   create mode 100644 libdtrace/drti-vers
>   create mode 100644 libdtrace/drti.c
>
> diff --git a/Makefunctions b/Makefunctions
> index 4909c0c91959..5945768bf983 100644
> --- a/Makefunctions
> +++ b/Makefunctions
> @@ -90,7 +90,7 @@ endef
>   # Syntax: $(call dof-template,primary,filename-without-dir)
>   
>   define dof-template
> -$(dof-name): $(src-name) $(objdir)/run-dtrace $(foreach source,$($(1)_SOURCES),$(call obj-name,$(1),$(source))) $(filter-out $(dof-name),$(foreach dep,$(filter %.o,$($(1)_DEPS)),$(call obj-name,$(1),$(dep)))) $(other-dlib-targets)
> +$(dof-name): $(src-name) $(objdir)/run-dtrace $(foreach source,$($(1)_SOURCES),$(call obj-name,$(1),$(source))) $(filter-out $(dof-name),$(foreach dep,$(filter %.o,$($(1)_DEPS)),$(call obj-name,$(1),$(dep)))) $(other-dlib-targets) $(DRTI_OBJ)
>   	$(call describe-target,GENDOF,$(src-name))
>   	$(objdir)/run-dtrace -x nolibs -G -o $(dof-name) -s $(src-name) $(foreach source,$($(1)_SOURCES),$(call obj-name,$(1),$(source))) $(filter-out $(dof-name),$(foreach dep,$(filter %.o,$($(1)_DEPS)),$(call obj-name,$(1),$(dep))))
>   endef
> diff --git a/libdtrace/Build b/libdtrace/Build
> index f1ee0d1c9a22..bc24fdd6d36d 100644
> --- a/libdtrace/Build
> +++ b/libdtrace/Build
> @@ -145,6 +145,7 @@ override other-dlib-targets = $(foreach kernel,$(SHORTKERNELS), \
>   $(objdir)/dlibs/.dir.stamp:
>   	mkdir -p $(objdir)/dlibs $(foreach kernel,$(SHORTKERNELS),$(objdir)/dlibs/$(kernel))
>   	@touch $(objdir)/dlibs/.dir.stamp
> +	ln -sf ../../$(libdtrace-build_DIR)/drti-vers $(objdir)/dlibs
>   
>   define dlib-kernel-ver-template
>   $(objdir)/dlibs/$(shell printf %s $(1) | sed -e 's/^\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*$$/\1.\2.\3/')/%.d: override SHORTKERNELVER := $(shell printf %s $(1) | sed -e 's/^\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*$$/\1.\2.\3/' | awk -F. '{ print $$1 * 1000 * 1000 + $$2 * 1000 + $$3 }')
> @@ -202,6 +203,25 @@ PHONIES += dlibs
>   TARGETS += dlibs
>   dlibs: $(m4-dlib-targets) $(other-dlib-targets)
>   
> +PHONIES += objs
> +TARGETS += objs
> +BUILD_DRTI_OBJ = $(objdir)/drti.o
> +DRTI_OBJ = $(objdir)/dlibs/drti.o
> +BUILD_DRTI32_OBJ = $(objdir)/drti32.o
> +DRTI32_OBJ = $(if $(NATIVE_BITNESS_ONLY),,$(objdir)/dlibs/drti32.o)
> +
> +objs: $(DRTI_OBJ) $(DRTI32_OBJ)
> +$(BUILD_DRTI_OBJ): $(libdtrace-build_DIR)drti.c
> +	$(call describe-target,CC,$<)
> +	$(CC) $(filter-out --coverage,$(CFLAGS)) -fPIC $(CPPFLAGS) $(libdtrace-build_CPPFLAGS) -MP -MMD -c -o $@ $<
> +$(DRTI_OBJ): $(BUILD_DRTI_OBJ) $(objdir)/dlibs/.dir.stamp
> +	ln -sf $(BUILD_DRTI_OBJ) $(DRTI_OBJ)
> +$(BUILD_DRTI32_OBJ): $(libdtrace-build_DIR)drti.c
> +	$(call describe-target,CC-32,$<)
> +	$(CC) $(filter-out --coverage,$(CFLAGS)) -m32 -fPIC $(CPPFLAGS) $(libdtrace-build_CPPFLAGS) -MP -MMD -c -o $@ $<
> +$(DRTI32_OBJ): $(BUILD_DRTI32_OBJ) $(objdir)/dlibs/.dir.stamp
> +	ln -sf $(BUILD_DRTI32_OBJ) $(DRTI32_OBJ)
> +
>   # Custom substitutions.
>   
>   # Though we use errno.h, the sensitive dependency is linux/errno.h,
> @@ -236,6 +256,12 @@ install::
>   	ln -sf libdtrace.so.$(libdtrace_VERSION) $(INSTLIBDIR)/$(libdtrace_SONAME)
>   	$(call describe-install-target,$(INSTLIBDIR),$(libdtrace_TARGET).so)
>   	ln -sf libdtrace.so.$(libdtrace_VERSION) $(INSTLIBDIR)/$(libdtrace_TARGET).so
> +	$(call describe-install-target,$(INSTLIBDIR)/dtrace,$(DRTI_OBJ))
> +	install -m 644 $(DRTI_OBJ) $(INSTLIBDIR)/dtrace
> +	$(call describe-install-target,$(INSTLIBDIR)/dtrace,$(DRTI32_OBJ))
> +	$(if $(NATIVE_BITNESS_ONLY),,install -m 644 $(DRTI32_OBJ) $(INSTLIBDIR)/dtrace)
> +	$(call describe-install-target,$(INSTLIBDIR)/dtrace,drti-vers)
> +	install -m 644 $(objdir)/dlibs/drti-vers $(INSTLIBDIR)/dtrace
>   	for kernel in $(SHORTKERNELS); do \
>   		$(call describe-expanded-install-target,$(INSTLIBDIR)/dtrace/$$kernel,$(WORKING_DLIBS)) \
>   		mkdir -p $(INSTLIBDIR)/dtrace/$$kernel && \
> diff --git a/libdtrace/drti-vers b/libdtrace/drti-vers
> new file mode 100644
> index 000000000000..8862dc291df1
> --- /dev/null
> +++ b/libdtrace/drti-vers
> @@ -0,0 +1 @@
> +{ local: *; };
> diff --git a/libdtrace/drti.c b/libdtrace/drti.c
> new file mode 100644
> index 000000000000..cabc316b0a00
> --- /dev/null
> +++ b/libdtrace/drti.c
> @@ -0,0 +1,193 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2008, 2015, 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.
> + */
> +
> +#include <unistd.h>
> +#include <fcntl.h>
> +#include <dlfcn.h>
> +#include <link.h>
> +#include <sys/dtrace.h>
> +#include <sys/compiler.h>
> +#include <sys/ioctl.h>
> +
> +#include <gelf.h>
> +
> +#include <limits.h>
> +#include <stdarg.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <errno.h>
> +
> +/*
> + * In Solaris 10 GA, the only mechanism for communicating helper information
> + * is through the DTrace helper pseudo-device node in /devices; there is
> + * no /dev link. Because of this, USDT providers and helper actions don't
> + * work inside of non-global zones. This issue was addressed by adding
> + * the /dev and having this initialization code use that /dev link. If the
> + * /dev link doesn't exist it falls back to looking for the /devices node
> + * as this code may be embedded in a binary which runs on Solaris 10 GA.
> + *
> + * Users may set the following environment variables to affect the way
> + * helper initialization takes place:
> + *
> + *	DTRACE_DOF_INIT_DEBUG		enable debugging output
> + *	DTRACE_DOF_INIT_DISABLE		disable helper loading
> + *	DTRACE_DOF_INIT_DEVNAME		set the path to the helper node
> + */
> +
> +static const char *devname = "/dev/dtrace/helper";
> +
> +static const char *modname;	/* Name of this load object */
> +static int gen;			/* DOF helper generation */
> +extern dof_hdr_t __SUNW_dof;	/* DOF defined in the .SUNW_dof section */
> +static boolean_t dof_init_debug = B_FALSE;	/* From DTRACE_DOF_INIT_DEBUG */
> +
> +_dt_constructor_(dtrace_dof_init)
> +static void
> +dtrace_dof_init(void)
> +{
> +	dof_hdr_t *dof = &__SUNW_dof;
> +#ifdef _LP64
> +	Elf64_Ehdr *elf;
> +#else
> +	Elf32_Ehdr *elf;
> +#endif
> +	dof_helper_t dh;
> +	struct link_map *lmp = NULL;
> +	Lmid_t lmid = -1;
> +	int fd;
> +	const char *p;
> +#if 1
> +	char mfn[PATH_MAX];		/* "/proc/<pid>/maps" */
> +	char str[4096];			/* read buffer */
> +	FILE *fp;
> +	struct link_map fmap = { 0x0, };
> +#endif
> +
> +	if (getenv("DTRACE_DOF_INIT_DISABLE") != NULL)
> +		return;
> +
> +	if (getenv("DTRACE_DOF_INIT_DEBUG") != NULL)
> +		dof_init_debug = B_TRUE;
> +
> +	if ((p = getenv("DTRACE_DOF_INIT_DEVNAME")) != NULL)
> +		devname = p;
> +
> +	if ((fd = open(devname, O_RDWR)) < 0) {
> +		if (dof_init_debug)
> +			dprintf(2, "DRTI: Failed to open helper device %s\n",
> +				devname);
> +		return;
> +	}
> +
> +#if 0
> +	if (dlinfo(RTLD_SELF, RTLD_DI_LINKMAP, &lmp) == -1) {
> +		dprintf(2, "DRTI: Couldn't discover module name or address.\n");
> +                goto out;
> +	}
> +
> +	if (dlinfo(RTLD_SELF, RTLD_DI_LMID, &lmid) == -1) {
> +		dprintf(2, "DRTI: Couldn't discover link map ID.\n");
> +                goto out;
> +	}
> +#else
> +	lmid = 0;			/* We need a way to determine this. */
> +
> +	snprintf(mfn, sizeof(mfn), "/proc/%d/maps", getpid());
> +	if ((fp = fopen(mfn, "re")) == NULL) {
> +		dprintf(2, "DRTI: Failed to open maps file.\n");
> +                goto out;
> +	}
> +	while (fgets(str, sizeof(str), fp) != NULL) {
> +		uintptr_t	start, end;
> +		char		*p = str, *q;
> +
> +		start = strtoul(p, &p, 16);
> +		if (*p != '-')
> +			continue;
> +
> +		end = strtoul(++p, &p, 16);
> +
> +		if (start > (uintptr_t)dtrace_dof_init ||
> +		    (uintptr_t)dtrace_dof_init > end)
> +			continue;
> +
> +		if ((p = strrchr(str, ' ')) == NULL)
> +			continue;
> +		if ((q = strchr(p, '\n')) != NULL)
> +			*q = '\0';
> +
> +		fmap.l_addr = start;
> +		fmap.l_name = p + 1;
> +		lmp = &fmap;
> +
> +		break;
> +	}
> +	fclose(fp);
> +#endif
> +	if (_dt_unlikely_(lmp == NULL)) {
> +		dprintf(2, "DRTI: Couldn't discover module name or address.\n");
> +                goto out;
> +	}
> +
> +	if ((modname = strrchr(lmp->l_name, '/')) == NULL)
> +		modname = lmp->l_name;
> +	else
> +		modname++;
> +
> +	if (dof->dofh_ident[DOF_ID_MAG0] != DOF_MAG_MAG0 ||
> +	    dof->dofh_ident[DOF_ID_MAG1] != DOF_MAG_MAG1 ||
> +	    dof->dofh_ident[DOF_ID_MAG2] != DOF_MAG_MAG2 ||
> +	    dof->dofh_ident[DOF_ID_MAG3] != DOF_MAG_MAG3) {
> +		dprintf(2, "DRTI: .SUNW_dof section corrupt in %s.\n",
> +			lmp->l_name);
> +                goto out;
> +	}
> +
> +	elf = (void *)lmp->l_addr;
> +
> +	dh.dofhp_dof = (uintptr_t)dof;
> +	dh.dofhp_addr = elf->e_type == ET_DYN ? lmp->l_addr : 0;
> +
> +	if (lmid == 0) {
> +		(void) snprintf(dh.dofhp_mod, sizeof (dh.dofhp_mod),
> +		    "%s", modname);
> +	} else {
> +		(void) snprintf(dh.dofhp_mod, sizeof (dh.dofhp_mod),
> +		    "LM%lu`%s", lmid, modname);
> +	}
> +
> +	if ((gen = ioctl(fd, DTRACEHIOC_ADDDOF, &dh)) == -1)
> +		dprintf(2, "DRTI: Ioctl failed for DOF at %p\n", (void *)dof);
> +	else if (dof_init_debug)
> +		dprintf(2, "DRTI: Ioctl OK for DOF at %p (gen %d)\n",
> +			(void *)dof, gen);
> +
> + out:
> +	close(fd);
> +}
> +
> +_dt_destructor_(dtrace_dof_fini)
> +static void
> +dtrace_dof_fini(void)
> +{
> +	int fd;
> +
> +	if ((fd = open(devname, O_RDWR | O_CLOEXEC)) < 0) {
> +		if (dof_init_debug)
> +			dprintf(2, "DRTI: Failed to open helper device %s\n",
> +				devname);
> +		return;
> +	}
> +
> +	if ((gen = ioctl(fd, DTRACEHIOC_REMOVE, gen)) == -1)
> +		dprintf(2, "DRTI: Ioctl failed to remove DOF (gen %d)\n", gen);
> +	else if (dof_init_debug)
> +		dprintf(2, "DRTI: Ioctl removed DOF (gen %d)\n", gen);
> +
> +	close(fd);
> +}
> diff --git a/libdtrace/dt_link.c b/libdtrace/dt_link.c
> index 187f8d89d693..766b97420db3 100644
> --- a/libdtrace/dt_link.c
> +++ b/libdtrace/dt_link.c
> @@ -1570,6 +1570,7 @@ int
>   dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
>       const char *file, int objc, char *const objv[])
>   {
> +	char drti[PATH_MAX], symvers[PATH_MAX];
>   	dof_hdr_t *dof;
>   	int fd, status, i, cur;
>   	char *cmd;
> @@ -1634,8 +1635,8 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
>   
>   	/*
>   	 * Create a temporary file and then unlink it if we're going to
> -	 * link later.  We can still refer to it in child processes as
> -	 * /dev/fd/<fd>.
> +	 * combine it with drti.o later.  We can still refer to it in child
> +	 * processes as /dev/fd/<fd>.
>   	 */
>   	if ((fd = open64(file, O_RDWR | O_CREAT | O_TRUNC, 0666)) == -1)
>   		return dt_link_error(dtp, NULL, -1, NULL,
> @@ -1681,7 +1682,8 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
>   		    "failed to write %s: %s", file, strerror(errno));
>   
>   	if (!dtp->dt_lazyload) {
> -		const char *fmt = "%s%s -o %s -r /dev/fd/%d";
> +		dt_dirpath_t *libdir = dt_list_next(&dtp->dt_lib_path);
> +		const char *fmt = "%s%s -o %s -r --version-script=%s /dev/fd/%d %s";
>   		const char *emu;
>   
>   		/*
> @@ -1690,19 +1692,25 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
>   		 */
>   
>   		if (dtp->dt_oflags & DTRACE_O_ILP32) {
> +			snprintf(drti, sizeof (drti), "%s/drti32.o", libdir->dir_path);
>   #if defined(__sparc)
>   			emu = " -m elf32_sparc";
>   #elif defined(__i386) || defined(__amd64)
>   			emu = " -m elf_i386";
>   #endif
> -		} else
> +		} else {
> +			snprintf(drti, sizeof (drti), "%s/drti.o", libdir->dir_path);
>   			emu = "";
> +		}
> +		snprintf(symvers, sizeof (symvers), "%s/drti-vers", libdir->dir_path);
> +
> +		len = snprintf(NULL, 0, fmt, dtp->dt_ld_path, emu, file,
> +			       symvers, fd, drti) + 1;
>   
> -		len = snprintf(NULL, 0, fmt, dtp->dt_ld_path, emu, file, fd) +
> -		      1;
>   		cmd = alloca(len);
>   
> -		snprintf(cmd, len, fmt, dtp->dt_ld_path, emu, file, fd);
> +		(void) snprintf(cmd, len, fmt, dtp->dt_ld_path, emu, file,
> +				symvers, fd, drti);
>   
>   		if ((status = system(cmd)) == -1) {
>   			ret = dt_link_error(dtp, NULL, -1, NULL,



More information about the DTrace-devel mailing list