[DTrace-devel] [PATCH 18/20] Optimize the memcpy implementation and make it more robust

Kris Van Hees kris.van.hees at oracle.com
Tue Jun 1 22:48:23 PDT 2021


The memcpy() implementation in BPF was more complicated than it needed
to be.  As a result, the BPF verifier was not able to always guarantee
that this function was being used in a safe way.  The simplification of
the implementation resolves this.

Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
 bpf/memcpy.c | 47 ++++++++++++++++++++++++++---------------------
 1 file changed, 26 insertions(+), 21 deletions(-)

diff --git a/bpf/memcpy.c b/bpf/memcpy.c
index 6e0d17f4..8db56535 100644
--- a/bpf/memcpy.c
+++ b/bpf/memcpy.c
@@ -9,16 +9,17 @@
 # define noinline	__attribute__((noinline))
 #endif
 
-noinline int dt_memcpy_int(void *dst, void *src, size_t n)
+noinline int dt_memcpy_int(void *dst, const void *src, size_t n)
 {
 	uint64_t	*d = dst;
-	uint64_t	*s = src;
-	size_t		r, i;
+	const uint64_t	*s = src;
+	size_t		q;
 
 	if (n > 128)
 		return -1;
 
-	switch (n / 8) {
+	q = n / 8;
+	switch (q) {
 	case 16:
 		d[15] = s[15];
 	case 15:
@@ -53,21 +54,24 @@ noinline int dt_memcpy_int(void *dst, void *src, size_t n)
 		d[0] = s[0];
 	}
 
-	r = n % 8;
-	if (r >= 4) {
-		i = (n / 4) - 1;
-		((uint32_t *)dst)[i] = ((uint32_t *)src)[i];
-		r -= 4;
-	}
-	if (r >= 2) {
-		i = (n / 2) - 1;
-		((uint16_t *)dst)[i] = ((uint16_t *)src)[i];
-		r -= 2;
+	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 (r) {
-		i = n - 1;
-		((uint8_t *)dst)[i] = ((uint8_t *)src)[i];
+	if (n & 2) {
+		*(uint16_t *)dst = *(uint16_t *)src;
+		dst += 2;
+		src += 2;
 	}
+	if (n & 1)
+		*(uint8_t *)dst = *(uint8_t *)src;
 
 	return 0;
 }
@@ -79,17 +83,18 @@ noinline int dt_memcpy_int(void *dst, void *src, size_t n)
  *
  * The size (n) must be no more than 256.
  */
-noinline int dt_memcpy(void *dst, void *src, size_t n)
+noinline int dt_memcpy(void *dst, const void *src, size_t n)
 {
 	uint64_t	*d = dst;
-	uint64_t	*s = src;
+	const uint64_t	*s = src;
+
+	if (n == 0)
+		return 0;
 
 	if (n > 128) {
 		if (dt_memcpy_int(d, s, 128))
 			return -1;
 		n -= 128;
-		if (n == 0)
-			return 0;
 
 		d += 16;
 		s += 16;
-- 
2.31.1




More information about the DTrace-devel mailing list