Browse Source

feat(aya-ebpf): Implement memmove

The compiler will emit this function for certain operations, but aya
currently does not provide an implementation.
This leads to ebpf loading failures as the kernel can't find the symbol when
loading the program.

The implementation is based on https://github.com/rust-lang/compiler-builtins/blob/master/src/mem/mod.rs#L29-L40
and https://github.com/rust-lang/compiler-builtins/blob/master/src/mem/impls.rs#L128-L135
Only the simplest case has been implemented, none of the word optimizations,
since memcpy also doesn't seem to have them.
Wouter Dullaert 8 months ago
parent
commit
7ad3926d99
1 changed files with 24 additions and 0 deletions
  1. 24 0
      ebpf/aya-ebpf/src/lib.rs

+ 24 - 0
ebpf/aya-ebpf/src/lib.rs

@@ -73,11 +73,35 @@ pub unsafe extern "C" fn memset(s: *mut u8, c: c_int, n: usize) {
 
 #[no_mangle]
 pub unsafe extern "C" fn memcpy(dest: *mut u8, src: *mut u8, n: usize) {
+    copy_forward(dest, src, n);
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn memmove(dest: *mut u8, src: *mut u8, n: usize) {
+    let delta = (dest as usize).wrapping_sub(src as usize);
+    if delta >= n {
+        // We can copy forwards because either dest is far enough ahead of src,
+        // or src is ahead of dest (and delta overflowed).
+        copy_forward(dest, src, n);
+    } else {
+        copy_backward(dest, src, n);
+    }
+}
+
+#[inline(always)]
+unsafe fn copy_forward(dest: *mut u8, src: *mut u8, n: usize) {
     for i in 0..n {
         *dest.add(i) = *src.add(i);
     }
 }
 
+#[inline(always)]
+unsafe fn copy_backward(dest: *mut u8, src: *mut u8, n: usize) {
+    for i in (0..n).rev() {
+        *dest.add(i) = *src.add(i);
+    }
+}
+
 /// Check if a value is within a range, using conditional forms compatible with
 /// the verifier.
 #[inline(always)]