[DTrace-devel] [PATCH] Replace dt_memcpy() with bpf_probe_read()

Kris Van Hees kris.van.hees at oracle.com
Thu Aug 19 23:46:41 PDT 2021


The dt_memcpy() functionality can be provided by the bpf_probe_read()
helper.  Thanks to Eugene Loh for pointing this out.

Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
 bpf/Build            |   1 -
 bpf/memcpy.c         | 106 -------------------------------------------
 libdtrace/dt_cg.c    |  39 +++++++---------
 libdtrace/dt_dlibs.c |   1 -
 4 files changed, 17 insertions(+), 130 deletions(-)
 delete mode 100644 bpf/memcpy.c

diff --git a/bpf/Build b/bpf/Build
index a436bc96..e08a28b6 100644
--- a/bpf/Build
+++ b/bpf/Build
@@ -25,7 +25,6 @@ bpf_dlib_SOURCES = \
 	agg_lqbin.c agg_qbin.c \
 	get_bvar.c \
 	get_tvar.c set_tvar.c \
-	memcpy.c \
 	probe_error.c \
 	strnlen.c \
 	varint.c
diff --git a/bpf/memcpy.c b/bpf/memcpy.c
deleted file mode 100644
index 77c7463f..00000000
--- a/bpf/memcpy.c
+++ /dev/null
@@ -1,106 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
- */
-#include <stddef.h>
-#include <stdint.h>
-
-#ifndef noinline
-# define noinline	__attribute__((noinline))
-#endif
-
-noinline int dt_memcpy_int(void *dst, const void *src, size_t n)
-{
-	uint64_t	*d = dst;
-	const uint64_t	*s = src;
-	size_t		q;
-
-	if (n > 128)
-		return -1;
-
-	q = n / 8;
-	switch (q) {
-	case 16:
-		d[15] = s[15];
-	case 15:
-		d[14] = s[14];
-	case 14:
-		d[13] = s[13];
-	case 13:
-		d[12] = s[12];
-	case 12:
-		d[11] = s[11];
-	case 11:
-		d[10] = s[10];
-	case 10:
-		d[9] = s[9];
-	case 9:
-		d[8] = s[8];
-	case 8:
-		d[7] = s[7];
-	case 7:
-		d[6] = s[6];
-	case 6:
-		d[5] = s[5];
-	case 5:
-		d[4] = s[4];
-	case 4:
-		d[3] = s[3];
-	case 3:
-		d[2] = s[2];
-	case 2:
-		d[1] = s[1];
-	case 1:
-		d[0] = s[0];
-	}
-
-	if ((n % 8) == 0)
-		return 0;
-
-	dst = &d[q];
-	src = &s[q];
-
-	if (n & 4) {
-		*(uint32_t *)dst = *(uint32_t *)src;
-		dst += 4;
-		src += 4;
-	}
-	if (n & 2) {
-		*(uint16_t *)dst = *(uint16_t *)src;
-		dst += 2;
-		src += 2;
-	}
-	if (n & 1)
-		*(uint8_t *)dst = *(uint8_t *)src;
-
-	return 0;
-}
-
-/*
- * Copy a byte sequence of length n from src to dst.  The function returns 0
- * upon success and -1 when n is greater than 256.  Both src and dst must be on
- * a 64-bit address boundary.
- *
- * The size (n) must be no more than 256.
- */
-noinline int dt_memcpy(void *dst, const void *src, size_t n)
-{
-	uint64_t	*d = dst;
-	const uint64_t	*s = src;
-
-	if (n == 0)
-		return 0;
-	if (n > 256)
-		n = 256;
-
-	if (n > 128) {
-		if (dt_memcpy_int(d, s, 128))
-			return -1;
-		n -= 128;
-
-		d += 16;
-		s += 16;
-	}
-
-	return dt_memcpy_int(d, s, n);
-}
diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index be61b4b0..854816ec 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -725,17 +725,14 @@ dt_cg_fill_gap(dt_pcb_t *pcb, int gap)
 static void
 dt_cg_memcpy(dt_irlist_t *dlp, dt_regset_t *drp, int dst, int src, size_t size)
 {
-	dt_ident_t	*idp = dt_dlib_get_func(yypcb->pcb_hdl, "dt_memcpy");
-
-	assert(idp != NULL);
 	if (dt_regset_xalloc_args(drp) == -1)
 		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
 
 	emit(dlp,  BPF_MOV_REG(BPF_REG_1, dst));
-	emit(dlp,  BPF_MOV_REG(BPF_REG_2, src));
-	emit(dlp,  BPF_MOV_IMM(BPF_REG_3, size));
+	emit(dlp,  BPF_MOV_IMM(BPF_REG_2, size));
+	emit(dlp,  BPF_MOV_REG(BPF_REG_3, src));
 	dt_regset_xalloc(drp, BPF_REG_0);
-	emite(dlp, BPF_CALL_FUNC(idp->di_id), idp);
+	emit(dlp, BPF_CALL_HELPER(BPF_FUNC_probe_read));
 	dt_regset_free_args(drp);
 	/* FIXME: check BPF_REG_0 for error? */
 	dt_regset_free(drp, BPF_REG_0);
@@ -820,9 +817,9 @@ dt_cg_store_val(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind,
 		if (dt_regset_xalloc_args(drp) == -1)
 			longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
 		dt_regset_xalloc(drp, BPF_REG_0);
-		emit(dlp,  BPF_CALL_HELPER(BPF_FUNC_get_current_pid_tgid));
+		emit(dlp, BPF_CALL_HELPER(BPF_FUNC_get_current_pid_tgid));
 		dt_regset_free_args(drp);
-		emit(dlp,  BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xffffffff));
+		emit(dlp, BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xffffffff));
 		emit(dlp, BPF_STORE(BPF_DW, BPF_REG_9, off, BPF_REG_0));
 		dt_regset_free(drp, BPF_REG_0);
 
@@ -859,15 +856,15 @@ dt_cg_store_val(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind,
 			longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
 
 		/* Determine the number of bytes used for the length. */
-		emit(dlp,   BPF_MOV_REG(BPF_REG_1, reg));
+		emit(dlp,  BPF_MOV_REG(BPF_REG_1, reg));
 		idp = dt_dlib_get_func(yypcb->pcb_hdl, "dt_vint_size");
 		assert(idp != NULL);
 		dt_regset_xalloc(drp, BPF_REG_0);
-		emite(dlp,  BPF_CALL_FUNC(idp->di_id), idp);
+		emite(dlp, BPF_CALL_FUNC(idp->di_id), idp);
 
 		/* Add length of the string (adjusted for terminating byte). */
-		emit(dlp,   BPF_ALU64_IMM(BPF_ADD, reg, 1));
-		emit(dlp,   BPF_ALU64_REG(BPF_ADD, BPF_REG_0, reg));
+		emit(dlp,  BPF_ALU64_IMM(BPF_ADD, reg, 1));
+		emit(dlp,  BPF_ALU64_REG(BPF_ADD, BPF_REG_0, reg));
 		dt_regset_free(drp, reg);
 
 		/*
@@ -875,19 +872,17 @@ dt_cg_store_val(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind,
 		 * output buffer at [%r9 + off].  The amount of bytes copied is
 		 * the lesser of the data size and the maximum string size.
 		 */
-		emit(dlp,   BPF_MOV_REG(BPF_REG_1, BPF_REG_9));
-		emit(dlp,   BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, off));
-		emit(dlp,   BPF_MOV_REG(BPF_REG_2, dnp->dn_reg));
+		emit(dlp,  BPF_MOV_REG(BPF_REG_1, BPF_REG_9));
+		emit(dlp,  BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, off));
+		emit(dlp,  BPF_MOV_REG(BPF_REG_3, dnp->dn_reg));
 		dt_regset_free(drp, dnp->dn_reg);
-		emit(dlp,   BPF_MOV_REG(BPF_REG_3, BPF_REG_0));
+		emit(dlp,  BPF_MOV_REG(BPF_REG_2, BPF_REG_0));
 		dt_regset_free(drp, BPF_REG_0);
-		emit(dlp,   BPF_BRANCH_IMM(BPF_JLT, BPF_REG_3, size, vcopy));
-		emit(dlp,   BPF_MOV_IMM(BPF_REG_3, size));
-		idp = dt_dlib_get_func(yypcb->pcb_hdl, "dt_memcpy");
-		assert(idp != NULL);
+		emit(dlp,  BPF_BRANCH_IMM(BPF_JLT, BPF_REG_2, size, vcopy));
+		emit(dlp,  BPF_MOV_IMM(BPF_REG_2, size));
 		dt_regset_xalloc(drp, BPF_REG_0);
-		emitle(dlp, vcopy,
-			    BPF_CALL_FUNC(idp->di_id), idp);
+		emitl(dlp, vcopy,
+			   BPF_CALL_HELPER(BPF_FUNC_probe_read));
 		dt_regset_free_args(drp);
 		dt_regset_free(drp, BPF_REG_0);
 
diff --git a/libdtrace/dt_dlibs.c b/libdtrace/dt_dlibs.c
index 53abe2f7..5980768b 100644
--- a/libdtrace/dt_dlibs.c
+++ b/libdtrace/dt_dlibs.c
@@ -58,7 +58,6 @@ static const dt_ident_t		dt_bpf_symbols[] = {
 	DT_BPF_SYMBOL(dt_get_bvar, DT_IDENT_SYMBOL),
 	DT_BPF_SYMBOL(dt_get_string, DT_IDENT_SYMBOL),
 	DT_BPF_SYMBOL(dt_get_tvar, DT_IDENT_SYMBOL),
-	DT_BPF_SYMBOL(dt_memcpy, DT_IDENT_SYMBOL),
 	DT_BPF_SYMBOL(dt_set_tvar, DT_IDENT_SYMBOL),
 	DT_BPF_SYMBOL(dt_strnlen, DT_IDENT_SYMBOL),
 	/* BPF maps */
-- 
2.33.0




More information about the DTrace-devel mailing list