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

Nick Alcock nick.alcock at oracle.com
Wed Aug 10 22:06:53 UTC 2022


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,
-- 
2.37.1.265.g363c192786.dirty




More information about the DTrace-devel mailing list