[DTrace-devel] [PATCH 02/17] drti: reference first loaded segment of object containing dtrace_dof_init

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


From: "David P. McLean" <david.mclean at oracle.com>

Any ELF executable or shared library (object) that contains USDT probes
contains a DOF section which describes the probes and also contains a copy
of the dtrace_dof_init() function.  This dtrace_dof_init() function is used
to register the DOF data of the object with the kernel.

The dtrace_dof_init() function needs to identify what type of object it is
being invoked for because the address representation varies (for ELF object
file type ET_DYN the symbol values in the DOF are relative to the load
address of the object rather than absolute values).  The ELF object file
type is obtained from the ELF header and the ELF header is found in the
first mapping (or segment) of the object.

The implementation used previous to this commit was to loop through all
mappings looking for one that contains the address of the dtrace_dof_init()
function.  The assumption was that the executable code mapping with the
dtrace_dof_init() function would always be the first mapping, and since the
ELF header is in the first mapping, the mapping with the dtrace_dof_init()
function would also contain the ELF header.

The assumption was proven wrong where sometimes the dtrace_dof_init()
function is not in the first mapping, and this commit updates the code to:
First loop over the mappings to determine the name of the object containing
the executing dtrace_dof_init() instance and record this object name.
Then a second loop is run over the mappings to determine the mapping with
the lowest start address (which is in fact the first mapping whose name
matches the one recorded from the first loop).

This first mapping of the object contains the ELF header (this ELF header is
used to determine the ELF object file type) and the first mapping start
address is the base address to be passed to the kernel along with the DOF
data.

Signed-off-by: David  Mc Lean <david.mclean at oracle.com>
Reviewed-by: Kris Van Hees <kris.van.hees at oracle.com>
---
 libdtrace/drti.c | 41 ++++++++++++++++++++++++++++++++++-------
 1 file changed, 34 insertions(+), 7 deletions(-)

diff --git a/libdtrace/drti.c b/libdtrace/drti.c
index cabc316b0a00..a5faa678a1e0 100644
--- a/libdtrace/drti.c
+++ b/libdtrace/drti.c
@@ -1,6 +1,6 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2020, 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.
  */
@@ -61,12 +61,11 @@ dtrace_dof_init(void)
 	Lmid_t lmid = -1;
 	int fd;
 	const char *p;
-#if 1
 	char mfn[PATH_MAX];		/* "/proc/<pid>/maps" */
 	char str[4096];			/* read buffer */
+	char *enm = NULL;		/* pointer to target executable name */
 	FILE *fp;
 	struct link_map fmap = { 0x0, };
-#endif
 
 	if (getenv("DTRACE_DOF_INIT_DISABLE") != NULL)
 		return;
@@ -118,15 +117,43 @@ dtrace_dof_init(void)
 
 		if ((p = strrchr(str, ' ')) == NULL)
 			continue;
+		p++;  /* move past the leading space char */
 		if ((q = strchr(p, '\n')) != NULL)
 			*q = '\0';
+		enm = strdup(p); /* Save name of object w/ dtrace_dof_init */
+		break;
+	}
 
-		fmap.l_addr = start;
-		fmap.l_name = p + 1;
-		lmp = &fmap;
+	if (_dt_unlikely_(enm == NULL)) {
+		fclose(fp);
+		dprintf(2, "DRTI: Couldn't discover module name or address.\n");
+		goto out;
+	}
 
-		break;
+	/* Now start at the beginning & look for 1st segment of the target */
+	rewind(fp);
+	while (fgets(str, sizeof(str), fp) != NULL) {
+		uintptr_t	start;
+		char		*p = str, *q;
+
+		start = strtoul(p, &p, 16);
+		if (*p != '-')
+			continue;
+		if ((p = strrchr(str, ' ')) == NULL)
+			continue;
+		p++;  /* move past the leading space char */
+		if ((q = strchr(p, '\n')) != NULL)
+			*q = '\0';
+
+		/* If found the 1st segment of the target executable */
+		if (strcmp(enm, p) == 0) {
+			fmap.l_addr = start;  /* record start address */
+			fmap.l_name = p;
+			lmp = &fmap;
+			break;
+		}
 	}
+	free(enm);
 	fclose(fp);
 #endif
 	if (_dt_unlikely_(lmp == NULL)) {
-- 
2.37.1.265.g363c192786.dirty




More information about the DTrace-devel mailing list