[DTrace-devel] [PATCH 3/4] Report missing BPF dlib symbols as a proper compiler error

Kris Van Hees kris.van.hees at oracle.com
Wed Jun 10 08:23:32 PDT 2020


If a BPF dlib symbol was not found in the bpf_dlib.o object, a SEGV
would occur because the compiler would try to dereference a NULL
pointer.  This patch adds proper error handling for this case and
also fixes a few error handling cases where a goto was done to the
wrong label.

Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
 libdtrace/dt_cc.c    | 53 +++++++++++++++++++++++++++++++-------------
 libdtrace/dt_dlibs.c | 16 ++++++++-----
 libdtrace/dt_impl.h  |  2 +-
 3 files changed, 49 insertions(+), 22 deletions(-)

diff --git a/libdtrace/dt_cc.c b/libdtrace/dt_cc.c
index 2b687bb0..67834790 100644
--- a/libdtrace/dt_cc.c
+++ b/libdtrace/dt_cc.c
@@ -2181,7 +2181,7 @@ out:
 	return (err ? NULL : rv);
 }
 
-static uint_t
+static int
 dt_link_layout(dtrace_hdl_t *dtp, const dtrace_difo_t *dp, uint_t *insc,
 	       uint_t *relc)
 {
@@ -2195,6 +2195,7 @@ dt_link_layout(dtrace_hdl_t *dtp, const dtrace_difo_t *dp, uint_t *insc,
 		char            *name = &dp->dtdo_strtab[rp->dofr_name];
 		dt_ident_t      *idp = dt_dlib_get_func(dtp, name);
 		dtrace_difo_t   *rdp;
+		int		ipc;
 
 		if (idp == NULL ||			/* not found */
 		    idp->di_kind != DT_IDENT_SYMBOL ||	/* not external sym */
@@ -2203,14 +2204,19 @@ dt_link_layout(dtrace_hdl_t *dtp, const dtrace_difo_t *dp, uint_t *insc,
 
 		idp->di_flags |= DT_IDFLG_REF;
 
-		rdp = dt_dlib_get_func_difo(idp);
-		idp->di_id = dt_link_layout(dtp, rdp, insc, relc);
+		rdp = dt_dlib_get_func_difo(dtp, idp);
+		if (rdp == NULL)
+			return -1;
+		ipc = dt_link_layout(dtp, rdp, insc, relc);
+		if (ipc == -1)
+			return -1;
+		idp->di_id = ipc;
 	}
 
 	return pc;
 }
 
-static uint_t
+static int
 dt_link_construct(dtrace_hdl_t *dtp, dtrace_difo_t *dp,
 		  const dtrace_difo_t *sdp, dt_strtab_t *stab,
 		  uint_t *pcp, uint_t *rcp)
@@ -2280,6 +2286,7 @@ dt_link_construct(dtrace_hdl_t *dtp, dtrace_difo_t *dp,
 		char            *name = &sdp->dtdo_strtab[rp->dofr_name];
 		dt_ident_t      *idp = dt_dlib_get_func(dtp, name);
 		dtrace_difo_t   *rdp;
+		int		ipc;
 
 		if (idp == NULL ||			/* not found */
 		    idp->di_kind != DT_IDENT_SYMBOL ||	/* not external sym */
@@ -2288,15 +2295,20 @@ dt_link_construct(dtrace_hdl_t *dtp, dtrace_difo_t *dp,
 
 		idp->di_flags |= DT_IDFLG_REF;
 
-		rdp = dt_dlib_get_func_difo(idp);
-		idp->di_id = dt_link_construct(dtp, dp, rdp, stab, pcp, rcp);
+		rdp = dt_dlib_get_func_difo(dtp, idp);
+		if (rdp == NULL)
+			return -1;
+		ipc = dt_link_construct(dtp, dp, rdp, stab, pcp, rcp);
+		if (ipc == -1)
+			return -1;
+		idp->di_id = ipc;
 		nrp->dofr_data = idp->di_id;		/* set value */
 	}
 
 	return pc;
 }
 
-static uint_t
+static void
 dt_link_resolve(dtrace_hdl_t *dtp, dtrace_difo_t *dp)
 {
 	struct bpf_insn		*buf = dp->dtdo_buf;
@@ -2330,29 +2342,32 @@ dt_link_stmt(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, dtrace_stmtdesc_t *sdp,
 	uint_t		insc = 0;
 	uint_t		relc = 0;
 	dtrace_difo_t	*dp = sdp->dtsd_action->dtad_difo;
-	dtrace_difo_t	*fdp;
+	dtrace_difo_t	*fdp = NULL;
 	dt_strtab_t	*stab;
+	int		rc;
 
 	/*
 	 * Determine the layout of the final (linked) DIFO, and calculate the
 	 * total isntruction and relocation record counts..
 	 */
-	dt_link_layout(dtp, dp, &insc, &relc);
+	rc = dt_link_layout(dtp, dp, &insc, &relc);
 	dt_dlib_reset(dtp, B_TRUE);
+	if (rc == -1)
+		goto fail;
 
 	/*
 	 * Allocate memory for constructing the final DIFO.
 	 */
 	fdp = dt_zalloc(dtp, sizeof(dtrace_difo_t));
 	if (fdp == NULL)
-		goto fail;
+		goto nomem;
 	fdp->dtdo_buf = dt_calloc(dtp, insc, sizeof(struct bpf_insn));
 	if (fdp->dtdo_buf == NULL)
-		goto fail;
+		goto nomem;
 	fdp->dtdo_len = insc;
 	fdp->dtdo_breltab = dt_calloc(dtp, relc, sizeof(dof_relodesc_t));
 	if (fdp->dtdo_breltab == NULL)
-		goto fail;
+		goto nomem;
 	fdp->dtdo_brelen = relc;
 
 	/*
@@ -2362,10 +2377,12 @@ dt_link_stmt(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, dtrace_stmtdesc_t *sdp,
 	insc = relc = 0;
 	stab = dt_strtab_create(BUFSIZ);
 	if (stab == NULL)
-		goto fail;
+		goto nomem;
 
-	dt_link_construct(dtp, fdp, dp, stab, &insc, &relc);
+	rc = dt_link_construct(dtp, fdp, dp, stab, &insc, &relc);
 	dt_dlib_reset(dtp, B_FALSE);
+	if (rc == -1)
+		goto fail;
 
 	/*
 	 * Replace the program DIFO instruction buffer, BPF relocation table,
@@ -2386,7 +2403,7 @@ dt_link_stmt(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, dtrace_stmtdesc_t *sdp,
 	if (dp->dtdo_strlen > 0) {
 		dp->dtdo_strtab = dt_zalloc(dtp, dp->dtdo_strlen);
 		if (dp->dtdo_strtab == NULL)
-			goto fail;
+			goto nomem;
 		dt_strtab_write(stab, (dt_strtab_write_f *)dt_strtab_copystr,
 				dp->dtdo_strtab);
 	} else
@@ -2410,7 +2427,11 @@ fail:
 		dt_free(dtp, fdp);
 	}
 
-	return dt_set_errno(dtp, EDT_NOMEM);
+	return rc;
+
+nomem:
+	rc = dt_set_errno(dtp, EDT_NOMEM);
+	goto fail;
 }
 
 static int
diff --git a/libdtrace/dt_dlibs.c b/libdtrace/dt_dlibs.c
index 4bf8e29b..4a8dd00e 100644
--- a/libdtrace/dt_dlibs.c
+++ b/libdtrace/dt_dlibs.c
@@ -222,10 +222,16 @@ dt_dlib_get_var(dtrace_hdl_t *dtp, const char *name)
  * Return the DIFO for an external symbol.
  */
 dtrace_difo_t *
-dt_dlib_get_func_difo(const dt_ident_t *idp)
+dt_dlib_get_func_difo(dtrace_hdl_t *dtp, const dt_ident_t *idp)
 {
 	assert(idp->di_kind == DT_IDENT_SYMBOL);
-	assert(idp->di_data != NULL);
+
+	if (idp->di_data == NULL) {
+		dt_dlib_error(dtp, D_IDENT_UNDEF, "dlib symbol %s not found",
+			      idp->di_name);
+		dt_set_errno(dtp, EDT_COMPILER);
+		return NULL;
+	}
 
 	return ((dt_bpf_func_t *)idp->di_data)->difo;
 }
@@ -358,7 +364,7 @@ get_symbols(dtrace_hdl_t *dtp, Elf *elf, int syms_idx, int strs_idx,
 		name = elf_strptr(elf, strs_idx, sym.st_name);
 		if (name == NULL) {
 			dt_dlib_error(dtp, 0, "BPF ELF: no symbol name");
-			goto err;;
+			goto err;
 		}
 
 		if (sym.st_shndx == text_idx) {
@@ -485,7 +491,7 @@ get_symbols(dtrace_hdl_t *dtp, Elf *elf, int syms_idx, int strs_idx,
 	scn = elf_getscn(elf, text_idx);
 	if ((text = elf_getdata(scn, NULL)) == NULL) {
 		dt_dlib_error(dtp, 0, "BPF ELF: no .text data\n");
-		goto out;
+		goto err;
 	}
 
 	for (idx = 0; idx < symc; idx++) {
@@ -531,7 +537,7 @@ get_symbols(dtrace_hdl_t *dtp, Elf *elf, int syms_idx, int strs_idx,
 	scn = elf_getscn(elf, relo_idx);
 	if ((data = elf_getdata(scn, NULL)) == NULL) {
 		dt_dlib_error(dtp, 0, "BPF ELF: no relocation data");
-		goto out;
+		goto err;
 	}
 
 	/*
diff --git a/libdtrace/dt_impl.h b/libdtrace/dt_impl.h
index 34c3435d..40603ea8 100644
--- a/libdtrace/dt_impl.h
+++ b/libdtrace/dt_impl.h
@@ -760,7 +760,7 @@ extern void dt_dlib_init(dtrace_hdl_t *dtp);
 extern dt_ident_t *dt_dlib_get_func(dtrace_hdl_t *, const char *);
 extern dt_ident_t *dt_dlib_get_map(dtrace_hdl_t *, const char *);
 extern dt_ident_t *dt_dlib_get_var(dtrace_hdl_t *, const char *);
-extern dtrace_difo_t *dt_dlib_get_func_difo(const dt_ident_t *);
+extern dtrace_difo_t *dt_dlib_get_func_difo(dtrace_hdl_t *, const dt_ident_t *);
 extern void dt_dlib_reset(dtrace_hdl_t *dtp, boolean_t);
 extern int dt_load_libs(dtrace_hdl_t *dtp);
 
-- 
2.26.0




More information about the DTrace-devel mailing list