diff --git a/benches/elf_loader.rs b/benches/elf_loader.rs index 914fd5e2..081397c8 100644 --- a/benches/elf_loader.rs +++ b/benches/elf_loader.rs @@ -21,15 +21,13 @@ use test::Bencher; fn loader() -> Arc> { let mut loader = BuiltinProgram::new_loader(Config::default()); - loader - .register_function(b"log_64", bpf_syscall_u64) - .unwrap(); + loader.register_function(b"log", bpf_syscall).unwrap(); Arc::new(loader) } #[bench] -fn bench_load_elf(bencher: &mut Bencher) { - let mut file = File::open("tests/elfs/noro.so").unwrap(); +fn bench_load_sbpfv1(bencher: &mut Bencher) { + let mut file = File::open("tests/elfs/syscall_reloc_64_32.so").unwrap(); let mut elf = Vec::new(); file.read_to_end(&mut elf).unwrap(); let loader = loader(); @@ -39,19 +37,8 @@ fn bench_load_elf(bencher: &mut Bencher) { } #[bench] -fn bench_load_elf_without_syscall(bencher: &mut Bencher) { - let mut file = File::open("tests/elfs/noro.so").unwrap(); - let mut elf = Vec::new(); - file.read_to_end(&mut elf).unwrap(); - let loader = loader(); - bencher.iter(|| { - Executable::::from_elf(&elf, loader.clone()).unwrap() - }); -} - -#[bench] -fn bench_load_elf_with_syscall(bencher: &mut Bencher) { - let mut file = File::open("tests/elfs/noro.so").unwrap(); +fn bench_load_sbpfv2(bencher: &mut Bencher) { + let mut file = File::open("tests/elfs/syscall_static.so").unwrap(); let mut elf = Vec::new(); file.read_to_end(&mut elf).unwrap(); let loader = loader(); diff --git a/src/elf.rs b/src/elf.rs index c45dc965..996b31de 100644 --- a/src/elf.rs +++ b/src/elf.rs @@ -1336,7 +1336,7 @@ mod test { #[test] fn test_validate() { - let elf_bytes = std::fs::read("tests/elfs/noop.so").unwrap(); + let elf_bytes = std::fs::read("tests/elfs/relative_call.so").unwrap(); let elf = NewParser::parse(&elf_bytes).unwrap(); let mut header = elf.header().clone(); @@ -1414,7 +1414,7 @@ mod test { #[test] fn test_load() { - let mut file = File::open("tests/elfs/noop.so").expect("file open failed"); + let mut file = File::open("tests/elfs/relative_call.so").expect("file open failed"); let mut elf_bytes = Vec::new(); file.read_to_end(&mut elf_bytes) .expect("failed to read elf file"); @@ -1423,7 +1423,8 @@ mod test { #[test] fn test_load_unaligned() { - let mut elf_bytes = std::fs::read("tests/elfs/noop.so").expect("failed to read elf file"); + let mut elf_bytes = + std::fs::read("tests/elfs/relative_call.so").expect("failed to read elf file"); // The default allocator allocates aligned memory. Move the ELF slice to // elf_bytes.as_ptr() + 1 to make it unaligned and test unaligned // parsing. @@ -1435,7 +1436,7 @@ mod test { fn test_entrypoint() { let loader = loader(); - let mut file = File::open("tests/elfs/noop.so").expect("file open failed"); + let mut file = File::open("tests/elfs/syscall_static.so").expect("file open failed"); let mut elf_bytes = Vec::new(); file.read_to_end(&mut elf_bytes) .expect("failed to read elf file"); @@ -2047,7 +2048,7 @@ mod test { #[should_panic(expected = r#"validation failed: WritableSectionNotSupported(".data")"#)] fn test_writable_data_section() { let elf_bytes = - std::fs::read("tests/elfs/writable_data_section.so").expect("failed to read elf file"); + std::fs::read("tests/elfs/data_section.so").expect("failed to read elf file"); ElfExecutable::load(&elf_bytes, loader()).expect("validation failed"); } @@ -2068,20 +2069,20 @@ mod test { } #[test] - #[should_panic(expected = "validation failed: RelativeJumpOutOfBounds(43)")] - fn test_relative_call_oob_forward() { + #[should_panic(expected = "validation failed: RelativeJumpOutOfBounds(38)")] + fn test_relative_call_oob_backward() { let mut elf_bytes = - std::fs::read("tests/elfs/relative_call_sbpfv1.so").expect("failed to read elf file"); - LittleEndian::write_i32(&mut elf_bytes[0x1074..0x1078], 11); + std::fs::read("tests/elfs/relative_call.so").expect("failed to read elf file"); + LittleEndian::write_i32(&mut elf_bytes[0x104C..0x1050], -11i32); ElfExecutable::load(&elf_bytes, loader()).expect("validation failed"); } #[test] - #[should_panic(expected = "validation failed: RelativeJumpOutOfBounds(43)")] - fn test_relative_call_oob_backward() { + #[should_panic(expected = "validation failed: RelativeJumpOutOfBounds(41)")] + fn test_relative_call_oob_forward() { let mut elf_bytes = - std::fs::read("tests/elfs/relative_call_sbpfv1.so").expect("failed to read elf file"); - LittleEndian::write_i32(&mut elf_bytes[0x1074..0x1078], -16i32); + std::fs::read("tests/elfs/relative_call.so").expect("failed to read elf file"); + LittleEndian::write_i32(&mut elf_bytes[0x1064..0x1068], 5); ElfExecutable::load(&elf_bytes, loader()).expect("validation failed"); } } diff --git a/tests/elfs/bss_section.c b/tests/elfs/bss_section.c deleted file mode 100644 index af62eebf..00000000 --- a/tests/elfs/bss_section.c +++ /dev/null @@ -1,9 +0,0 @@ -typedef unsigned long int uint64_t; -typedef unsigned char uint8_t; - -int val = 0; - -extern uint64_t entrypoint(const uint8_t *input) { - val = 43; - return 0; -} diff --git a/tests/elfs/bss_section.rs b/tests/elfs/bss_section.rs new file mode 100644 index 00000000..3dc09dcf --- /dev/null +++ b/tests/elfs/bss_section.rs @@ -0,0 +1,7 @@ +static mut VAL: u64 = 0; + +#[no_mangle] +pub fn entrypoint() -> u64 { + unsafe { core::ptr::write_volatile(&mut VAL, 42); } + return 0; +} diff --git a/tests/elfs/bss_section.so b/tests/elfs/bss_section.so index fb87a951..48c14f7c 100755 Binary files a/tests/elfs/bss_section.so and b/tests/elfs/bss_section.so differ diff --git a/tests/elfs/data_section.rs b/tests/elfs/data_section.rs new file mode 100644 index 00000000..9fecdc5a --- /dev/null +++ b/tests/elfs/data_section.rs @@ -0,0 +1,7 @@ +static mut VAL: u64 = 42; + +#[no_mangle] +pub fn entrypoint() -> u64 { + unsafe { core::ptr::write_volatile(&mut VAL, 0); } + return 0; +} diff --git a/tests/elfs/syscall_static_unknown.so b/tests/elfs/data_section.so similarity index 71% rename from tests/elfs/syscall_static_unknown.so rename to tests/elfs/data_section.so index 1da65e31..8c85d240 100755 Binary files a/tests/elfs/syscall_static_unknown.so and b/tests/elfs/data_section.so differ diff --git a/tests/elfs/elf.ld b/tests/elfs/elf.ld index a72a70ce..e01debd2 100644 --- a/tests/elfs/elf.ld +++ b/tests/elfs/elf.ld @@ -2,19 +2,25 @@ PHDRS { text PT_LOAD ; rodata PT_LOAD ; + data PT_LOAD ; dynamic PT_DYNAMIC ; } SECTIONS { . = SIZEOF_HEADERS; - .text : { *(.text) } :text + .text : { *(.text*) } :text .rodata : { *(.rodata*) } :rodata - .data.rel.ro : { *(.data.rel.ro) } :rodata + .data.rel.ro : { *(.data.rel.ro*) } :rodata .dynamic : { *(.dynamic) } :dynamic - .dynsym : { *(.dynsym) } :dynamic - .dynstr : { *(.dynstr) } :dynamic - .gnu.hash : { *(.gnu.hash) } :dynamic - .rel.dyn : { *(.rel.dyn) } :dynamic - .hash : { *(.hash) } :dynamic + .dynsym : { *(.dynsym) } :data + .dynstr : { *(.dynstr) } :data + .rel.dyn : { *(.rel.dyn) } :data + .data : { *(.data*) } :data + .bss : { *(.bss*) } :data + /DISCARD/ : { + *(.eh_frame*) + *(.gnu.hash*) + *(.hash*) + } } diff --git a/tests/elfs/elfs.sh b/tests/elfs/elfs.sh index b03d7c27..1c208cdc 100755 --- a/tests/elfs/elfs.sh +++ b/tests/elfs/elfs.sh @@ -1,102 +1,59 @@ #!/bin/bash -ex # Requires Latest release of Solana's custom LLVM -#https://github.com/solana-labs/llvm-builder/releases - -LLVM_DIR=../../../solana/sdk/sbf/dependencies/sbf-tools/llvm/bin/ -CC_FLAGS_COMMON="-Werror -target sbf -O2 -fno-builtin -fPIC" -CC_FLAGS="$CC_FLAGS_COMMON -mcpu=sbfv2" -CC_FLAGS_V1="$CC_FLAGS_COMMON -mcpu=generic" -LD_FLAGS_COMMON="-z notext -shared --Bdynamic -entry entrypoint --script elf.ld" -LD_FLAGS="$LD_FLAGS_COMMON --section-start=.text=0x100000000" -LD_FLAGS_V1=$LD_FLAGS_COMMON - -"$LLVM_DIR"clang $CC_FLAGS -o noop.o -c noop.c -"$LLVM_DIR"ld.lld $LD_FLAGS -o noop.so noop.o -rm noop.o - -"$LLVM_DIR"clang $CC_FLAGS -o noro.o -c noro.c -"$LLVM_DIR"ld.lld $LD_FLAGS -o noro.so noro.o -rm noro.o - -"$LLVM_DIR"clang $CC_FLAGS -o empty_rodata.o -c empty_rodata.c -"$LLVM_DIR"ld.lld $LD_FLAGS -o empty_rodata.so empty_rodata.o -rm empty_rodata.o - -"$LLVM_DIR"clang $CC_FLAGS -o unresolved_syscall.o -c unresolved_syscall.c -"$LLVM_DIR"ld.lld $LD_FLAGS -o unresolved_syscall.so unresolved_syscall.o -rm unresolved_syscall.o - -"$LLVM_DIR"clang $CC_FLAGS -o entrypoint.o -c entrypoint.c -"$LLVM_DIR"clang $CC_FLAGS -o multiple_file.o -c multiple_file.c -"$LLVM_DIR"ld.lld $LD_FLAGS -o multiple_file.so entrypoint.o multiple_file.o -rm entrypoint.o -rm multiple_file.o - -"$LLVM_DIR"clang $CC_FLAGS_V1 -o reloc_64_64.o -c reloc_64_64.c -"$LLVM_DIR"ld.lld $LD_FLAGS_V1 -o reloc_64_64_sbpfv1.so reloc_64_64.o -rm reloc_64_64.o - -"$LLVM_DIR"clang $CC_FLAGS -o reloc_64_64.o -c reloc_64_64.c -"$LLVM_DIR"ld.lld $LD_FLAGS -o reloc_64_64.so reloc_64_64.o -rm reloc_64_64.o - -"$LLVM_DIR"clang $CC_FLAGS -o reloc_64_relative.o -c reloc_64_relative.c -"$LLVM_DIR"ld.lld $LD_FLAGS -o reloc_64_relative.so reloc_64_relative.o -rm reloc_64_relative.o - -"$LLVM_DIR"clang $CC_FLAGS_V1 -o reloc_64_relative.o -c reloc_64_relative.c -"$LLVM_DIR"ld.lld $LD_FLAGS_V1 -o reloc_64_relative_sbpfv1.so reloc_64_relative.o -rm reloc_64_relative.o - -"$LLVM_DIR"clang $CC_FLAGS_V1 -o reloc_64_relative_data.o -c reloc_64_relative_data.c -"$LLVM_DIR"ld.lld $LD_FLAGS_V1 -o reloc_64_relative_data_sbpfv1.so reloc_64_relative_data.o -rm reloc_64_relative_data.o - -"$LLVM_DIR"clang $CC_FLAGS -o reloc_64_relative_data.o -c reloc_64_relative_data.c -"$LLVM_DIR"ld.lld $LD_FLAGS -o reloc_64_relative_data.so reloc_64_relative_data.o -rm reloc_64_relative_data.o - -"$LLVM_DIR"clang $CC_FLAGS -o scratch_registers.o -c scratch_registers.c -"$LLVM_DIR"ld.lld $LD_FLAGS -o scratch_registers.so scratch_registers.o -rm scratch_registers.o - -"$LLVM_DIR"clang $CC_FLAGS -o pass_stack_reference.o -c pass_stack_reference.c -"$LLVM_DIR"ld.lld $LD_FLAGS -o pass_stack_reference.so pass_stack_reference.o -rm pass_stack_reference.o - -"$LLVM_DIR"clang $CC_FLAGS -o writable_data_section.o -c writable_data_section.c -"$LLVM_DIR"ld.lld $LD_FLAGS -o writable_data_section.so writable_data_section.o -rm writable_data_section.o - -"$LLVM_DIR"clang $CC_FLAGS -o bss_section.o -c bss_section.c -"$LLVM_DIR"ld.lld $LD_FLAGS -o bss_section.so bss_section.o -rm bss_section.o - -"$LLVM_DIR"clang $CC_FLAGS -o rodata.o -c rodata.c -"$LLVM_DIR"ld.lld $LD_FLAGS -o rodata.so rodata.o -rm rodata.o - -"$LLVM_DIR"clang $CC_FLAGS_V1 -mcpu=generic -o rodata.o -c rodata.c -"$LLVM_DIR"ld.lld $LD_FLAGS_V1 -o rodata_sbpfv1.so rodata.o -rm rodata.o - -"$LLVM_DIR"clang $CC_FLAGS -o syscall_static_unknown.o -c syscall_static_unknown.c -"$LLVM_DIR"ld.lld $LD_FLAGS -o syscall_static_unknown.so syscall_static_unknown.o -rm syscall_static_unknown.o - -"$LLVM_DIR"clang $CC_FLAGS -o syscall_static.o -c syscall_static.c -"$LLVM_DIR"ld.lld $LD_FLAGS -o syscall_static.so syscall_static.o -rm syscall_static.o - -"$LLVM_DIR"clang $CC_FLAGS -o program_headers_overflow.o -c rodata.c -"$LLVM_DIR"ld.lld -z notext -shared --Bdynamic -entry entrypoint --script program_headers_overflow.ld --noinhibit-exec -o program_headers_overflow.so program_headers_overflow.o -rm program_headers_overflow.o - -"$LLVM_DIR"clang $CC_FLAGS -fdebug-prefix-map=$(pwd)=. -o scratch_registers_debug.o -c scratch_registers.c -"$LLVM_DIR"ld.lld -z notext -shared --Bdynamic -entry entrypoint --section-start=.text=0x1000 -o scratch_registers_debug.so scratch_registers_debug.o -rm scratch_registers_debug.o - -"$LLVM_DIR"clang $CC_FLAGS -o struct_func_pointer.o -c struct_func_pointer.c -"$LLVM_DIR"ld.lld $LD_FLAGS -o struct_func_pointer.so struct_func_pointer.o -rm struct_func_pointer.o +# https://github.com/solana-labs/platform-tools/releases + +TOOLCHAIN=../../../solana/sdk/sbf/dependencies/sbf-tools +RC_COMMON="$TOOLCHAIN/rust/bin/rustc --target sbf-solana-solana --crate-type lib -C panic=abort -C opt-level=2" +RC="$RC_COMMON -C target_cpu=sbfv2" +RC_V1="$RC_COMMON -C target_cpu=generic" +LD_COMMON="$TOOLCHAIN/llvm/bin/ld.lld -z notext -shared --Bdynamic -entry entrypoint --script elf.ld" +LD="$LD_COMMON --section-start=.text=0x100000000" +LD_V1=$LD_COMMON + +$RC -o relative_call.o relative_call.rs +$LD -o relative_call.so relative_call.o + +$RC_V1 -o syscall_reloc_64_32.o syscall_reloc_64_32.rs +$LD_V1 -o syscall_reloc_64_32.so syscall_reloc_64_32.o + +$RC -o syscall_static.o syscall_static.rs +$LD -o syscall_static.so syscall_static.o + +$RC -o bss_section.o bss_section.rs +$LD -o bss_section.so bss_section.o + +$RC -o data_section.o data_section.rs +$LD -o data_section.so data_section.o + +$RC_V1 -o rodata_section.o rodata_section.rs +$LD_V1 -o rodata_section_sbpfv1.so rodata_section.o + +$RC -o rodata_section.o rodata_section.rs +$LD -o rodata_section.so rodata_section.o + +$RC -o program_headers_overflow.o rodata_section.rs +"$TOOLCHAIN"/llvm/bin/ld.lld -z notext -shared --Bdynamic -entry entrypoint --script program_headers_overflow.ld --noinhibit-exec -o program_headers_overflow.so program_headers_overflow.o + +$RC -o struct_func_pointer.o struct_func_pointer.rs +$LD -o struct_func_pointer.so struct_func_pointer.o + +$RC -o reloc_64_64.o reloc_64_64.rs +$LD -o reloc_64_64.so reloc_64_64.o + +$RC_V1 -o reloc_64_64.o reloc_64_64.rs +$LD_V1 -o reloc_64_64_sbpfv1.so reloc_64_64.o + +$RC -o reloc_64_relative.o reloc_64_relative.rs +$LD -o reloc_64_relative.so reloc_64_relative.o + +$RC_V1 -o reloc_64_relative.o reloc_64_relative.rs +$LD_V1 -o reloc_64_relative_sbpfv1.so reloc_64_relative.o + +# $RC -o reloc_64_relative_data.o reloc_64_relative_data.rs +# $LD -o reloc_64_relative_data.so reloc_64_relative_data.o# + +# $RC_V1 -o reloc_64_relative_data.o reloc_64_relative_data.rs +# $LD_V1 -o reloc_64_relative_data_sbpfv1.so reloc_64_relative_data.o + +rm *.o diff --git a/tests/elfs/empty_rodata.c b/tests/elfs/empty_rodata.c deleted file mode 100644 index 87b4b046..00000000 --- a/tests/elfs/empty_rodata.c +++ /dev/null @@ -1,10 +0,0 @@ -/** - * @brief test program - */ - -#include "syscalls.h" - -extern uint64_t entrypoint(const uint8_t *input) { - log_64(1, 2, 3, 4, 5); - return 0; -} diff --git a/tests/elfs/entrypoint.c b/tests/elfs/entrypoint.c deleted file mode 100644 index bd13ae51..00000000 --- a/tests/elfs/entrypoint.c +++ /dev/null @@ -1,22 +0,0 @@ -/** - * @brief test program that creates BPF to BPF calls - */ - -#include "syscalls.h" -#include "multiple_file.h" - -uint64_t function_bar(uint64_t x) { - log(__func__, sizeof(__func__)); - if (x) { - x = function_foo(--x); - } - return x; -} - -extern uint64_t entrypoint(const uint8_t *input) { - uint64_t x = (uint64_t)*input; - if (x) { - x = function_foo(--x); - } - return x; -} diff --git a/tests/elfs/multiple_file.c b/tests/elfs/multiple_file.c deleted file mode 100644 index 12956e88..00000000 --- a/tests/elfs/multiple_file.c +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @brief Syscall function used in the BPF to BPF call test - */ - -#include "syscalls.h" -#include "multiple_file.h" - -uint64_t function_foo(uint64_t x) { - log(__func__, sizeof(__func__)); - if (x) { - x = function_bar(--x); - } - return x; -} diff --git a/tests/elfs/multiple_file.h b/tests/elfs/multiple_file.h deleted file mode 100644 index bc3546bf..00000000 --- a/tests/elfs/multiple_file.h +++ /dev/null @@ -1,8 +0,0 @@ -/** - * @brief Syscall function used in the BPF to BPF call test - */ - -#pragma once - -uint64_t function_foo(uint64_t x); -uint64_t function_bar(uint64_t x); diff --git a/tests/elfs/multiple_file.so b/tests/elfs/multiple_file.so deleted file mode 100755 index a9c2e763..00000000 Binary files a/tests/elfs/multiple_file.so and /dev/null differ diff --git a/tests/elfs/noop.c b/tests/elfs/noop.c deleted file mode 100644 index 03c90b57..00000000 --- a/tests/elfs/noop.c +++ /dev/null @@ -1,11 +0,0 @@ -/** - * @brief test program - */ - -#include "syscalls.h" - -extern uint64_t entrypoint(const uint8_t *input) { - log(__func__, sizeof(__func__)); - log_64(1, 2, 3, 4, 5); - return 0; -} diff --git a/tests/elfs/noop.so b/tests/elfs/noop.so deleted file mode 100755 index f017a1a9..00000000 Binary files a/tests/elfs/noop.so and /dev/null differ diff --git a/tests/elfs/noro.c b/tests/elfs/noro.c deleted file mode 100644 index 87b4b046..00000000 --- a/tests/elfs/noro.c +++ /dev/null @@ -1,10 +0,0 @@ -/** - * @brief test program - */ - -#include "syscalls.h" - -extern uint64_t entrypoint(const uint8_t *input) { - log_64(1, 2, 3, 4, 5); - return 0; -} diff --git a/tests/elfs/pass_stack_reference.c b/tests/elfs/pass_stack_reference.c deleted file mode 100644 index a0398fa1..00000000 --- a/tests/elfs/pass_stack_reference.c +++ /dev/null @@ -1,35 +0,0 @@ -/** - * @brief test program that generates BPF PC relative call instructions - */ - -typedef unsigned char uint8_t; -typedef unsigned long int uint64_t; - -void __attribute__ ((noinline)) function_4(uint64_t* x) { - *x = 42; -} - -void __attribute__ ((noinline)) function_3(uint64_t* x) { - uint64_t array[256]; - function_4(&array[128]); - *x = array[128]; -} - -void __attribute__ ((noinline)) function_2(uint64_t* x) { - uint64_t array[256]; - function_3(&array[128]); - *x = array[128]; -} - -void __attribute__ ((noinline)) function_1(uint64_t* x) { - uint64_t array[256]; - function_2(&array[128]); - *x = array[128]; -} - -extern uint64_t entrypoint(const uint8_t *input) { - uint64_t array[256]; - function_1(&array[128]); - return array[128]; -} - diff --git a/tests/elfs/pass_stack_reference.so b/tests/elfs/pass_stack_reference.so deleted file mode 100755 index 2e9d2aa6..00000000 Binary files a/tests/elfs/pass_stack_reference.so and /dev/null differ diff --git a/tests/elfs/program_headers_overflow.so b/tests/elfs/program_headers_overflow.so index be60c249..7b346935 100755 Binary files a/tests/elfs/program_headers_overflow.so and b/tests/elfs/program_headers_overflow.so differ diff --git a/tests/elfs/relative_call.c b/tests/elfs/relative_call.c deleted file mode 100644 index d495557b..00000000 --- a/tests/elfs/relative_call.c +++ /dev/null @@ -1,26 +0,0 @@ -/** - * @brief test program that generates BPF PC relative call instructions - */ - -typedef unsigned char uint8_t; -typedef unsigned long int uint64_t; -extern void log(const char*, uint64_t); - -uint64_t function_bar(uint64_t x); -uint64_t __attribute__ ((noinline)) function_foo(uint64_t x) { - log(__func__, sizeof(__func__)); - return x + 1; -} - -extern uint64_t entrypoint(const uint8_t *input) { - uint64_t x = (uint64_t)*input; - log(__func__, sizeof(__func__)); - x = function_foo(x); - x = function_bar(x); - return x; -} - -uint64_t __attribute__ ((noinline)) function_bar(uint64_t x) { - log(__func__, sizeof(__func__)); - return x + 2; -} diff --git a/tests/elfs/relative_call.rs b/tests/elfs/relative_call.rs new file mode 100644 index 00000000..997e5d42 --- /dev/null +++ b/tests/elfs/relative_call.rs @@ -0,0 +1,20 @@ +#[inline(never)] +fn function_stack_ref(stack: &mut [u64]) -> u64 { + stack[0] += 1; + return stack[0]; +} + +#[no_mangle] +pub fn entrypoint(x: &u8) -> u64 { + let stack = core::mem::MaybeUninit::<[u64; 32]>::uninit(); + let mut stack = unsafe { stack.assume_init() }; + stack[0] = *x as u64; + let y = function_stack_ref(&mut stack); + let z = *x as u64; + return function_sum(y, z); +} + +#[inline(never)] +fn function_sum(x: u64, y: u64) -> u64 { + return x + y; +} diff --git a/tests/elfs/empty_rodata.so b/tests/elfs/relative_call.so similarity index 72% rename from tests/elfs/empty_rodata.so rename to tests/elfs/relative_call.so index 913460ed..6818a5e7 100755 Binary files a/tests/elfs/empty_rodata.so and b/tests/elfs/relative_call.so differ diff --git a/tests/elfs/relative_call_sbpfv1.so b/tests/elfs/relative_call_sbpfv1.so deleted file mode 100755 index f9a46758..00000000 Binary files a/tests/elfs/relative_call_sbpfv1.so and /dev/null differ diff --git a/tests/elfs/reloc_64_64.c b/tests/elfs/reloc_64_64.c deleted file mode 100644 index cb4a66fe..00000000 --- a/tests/elfs/reloc_64_64.c +++ /dev/null @@ -1,11 +0,0 @@ -/** - * @brief a program to test R_BPF_64_64 relocation handling - */ - -typedef unsigned long int uint64_t; -typedef unsigned char uint8_t; - -extern uint64_t entrypoint(const uint8_t *input) { - uint64_t (*ptr)(const uint8_t *) = entrypoint; - return (uint64_t) ptr; -} diff --git a/tests/elfs/reloc_64_64.rs b/tests/elfs/reloc_64_64.rs new file mode 100644 index 00000000..ab209989 --- /dev/null +++ b/tests/elfs/reloc_64_64.rs @@ -0,0 +1,4 @@ +#[no_mangle] +pub fn entrypoint() -> u64 { + return entrypoint as u64; +} diff --git a/tests/elfs/reloc_64_64.so b/tests/elfs/reloc_64_64.so index c3906368..44c42ee5 100755 Binary files a/tests/elfs/reloc_64_64.so and b/tests/elfs/reloc_64_64.so differ diff --git a/tests/elfs/reloc_64_64_sbpfv1.so b/tests/elfs/reloc_64_64_sbpfv1.so index 446194c9..a68fc3b7 100755 Binary files a/tests/elfs/reloc_64_64_sbpfv1.so and b/tests/elfs/reloc_64_64_sbpfv1.so differ diff --git a/tests/elfs/reloc_64_relative.c b/tests/elfs/reloc_64_relative.c deleted file mode 100644 index 247d1e43..00000000 --- a/tests/elfs/reloc_64_relative.c +++ /dev/null @@ -1,10 +0,0 @@ -/** - * @brief a program to test R_BPF_64_RELATIVE relocation handling - */ - -typedef unsigned long int uint64_t; -typedef unsigned char uint8_t; - -extern uint64_t entrypoint(const uint8_t *input) { - return (uint64_t) __func__; -} diff --git a/tests/elfs/reloc_64_relative.rs b/tests/elfs/reloc_64_relative.rs new file mode 100644 index 00000000..9a745451 --- /dev/null +++ b/tests/elfs/reloc_64_relative.rs @@ -0,0 +1,4 @@ +#[no_mangle] +pub fn entrypoint() -> u64 { + return "entrypoint".as_ptr() as u64; +} diff --git a/tests/elfs/reloc_64_relative.so b/tests/elfs/reloc_64_relative.so index 4644ad3d..795f38c7 100755 Binary files a/tests/elfs/reloc_64_relative.so and b/tests/elfs/reloc_64_relative.so differ diff --git a/tests/elfs/reloc_64_relative_sbpfv1.so b/tests/elfs/reloc_64_relative_sbpfv1.so index 658846e8..08641014 100755 Binary files a/tests/elfs/reloc_64_relative_sbpfv1.so and b/tests/elfs/reloc_64_relative_sbpfv1.so differ diff --git a/tests/elfs/rodata.c b/tests/elfs/rodata.c deleted file mode 100644 index 072d3cee..00000000 --- a/tests/elfs/rodata.c +++ /dev/null @@ -1,10 +0,0 @@ -typedef unsigned long int uint64_t; -typedef unsigned char uint8_t; - -volatile const uint64_t v1 = 41; -volatile const uint64_t v2 = 42; -volatile const uint64_t v3 = 43; - -extern uint64_t entrypoint(const uint8_t *input) { - return v2; -} diff --git a/tests/elfs/rodata.so b/tests/elfs/rodata.so deleted file mode 100755 index f7a1a819..00000000 Binary files a/tests/elfs/rodata.so and /dev/null differ diff --git a/tests/elfs/rodata_sbpfv1.so b/tests/elfs/rodata_sbpfv1.so deleted file mode 100755 index 3c884672..00000000 Binary files a/tests/elfs/rodata_sbpfv1.so and /dev/null differ diff --git a/tests/elfs/rodata_section.rs b/tests/elfs/rodata_section.rs new file mode 100644 index 00000000..74add7db --- /dev/null +++ b/tests/elfs/rodata_section.rs @@ -0,0 +1,8 @@ +static _VAL_A: u64 = 41; +static VAL_B: u64 = 42; +static _VAL_C: u64 = 43; + +#[no_mangle] +pub fn entrypoint() -> u64 { + return unsafe { core::ptr::read_volatile(&VAL_B) }; +} \ No newline at end of file diff --git a/tests/elfs/noro.so b/tests/elfs/rodata_section.so similarity index 70% rename from tests/elfs/noro.so rename to tests/elfs/rodata_section.so index daf428d6..037afdf6 100755 Binary files a/tests/elfs/noro.so and b/tests/elfs/rodata_section.so differ diff --git a/tests/elfs/rodata_section_sbpfv1.so b/tests/elfs/rodata_section_sbpfv1.so new file mode 100755 index 00000000..d61014d5 Binary files /dev/null and b/tests/elfs/rodata_section_sbpfv1.so differ diff --git a/tests/elfs/scratch_registers.c b/tests/elfs/scratch_registers.c deleted file mode 100644 index da026e63..00000000 --- a/tests/elfs/scratch_registers.c +++ /dev/null @@ -1,26 +0,0 @@ -/** - * @brief test program that generates BPF PC relative call instructions - */ - -#include "syscalls.h" - -uint64_t __attribute__ ((noinline)) log_wrapper(uint64_t x) { - log_64(0, 0, 0, 0, x); - return x; -} - -uint64_t __attribute__ ((noinline)) function_foo(uint64_t x) { - uint64_t y = 100; - uint64_t z = 10; - x += log_wrapper(x); - x += log_wrapper(y); - x += log_wrapper(z); - return x; -} - -extern uint64_t entrypoint(const uint8_t *input) { - uint64_t x = (uint64_t)*input; - x = function_foo(x); - return x; -} - diff --git a/tests/elfs/scratch_registers.so b/tests/elfs/scratch_registers.so deleted file mode 100755 index f1da1850..00000000 Binary files a/tests/elfs/scratch_registers.so and /dev/null differ diff --git a/tests/elfs/scratch_registers_debug.so b/tests/elfs/scratch_registers_debug.so deleted file mode 100755 index 70581390..00000000 Binary files a/tests/elfs/scratch_registers_debug.so and /dev/null differ diff --git a/tests/elfs/struct_func_pointer.c b/tests/elfs/struct_func_pointer.c deleted file mode 100644 index 64ee81e8..00000000 --- a/tests/elfs/struct_func_pointer.c +++ /dev/null @@ -1,17 +0,0 @@ -typedef unsigned long int uint64_t; -typedef unsigned char uint8_t; - -struct PubkeyLutEntry { - uint8_t (*fp)(uint8_t); - uint64_t key; -}; - -uint8_t f1(uint8_t a) { - return a + 1; -} - -struct PubkeyLutEntry __attribute__((__section__(".data.rel.ro"))) E1 = { &f1, 0x0102030405060708 }; - -extern uint64_t entrypoint(const uint8_t *input) { - return E1.key; -} diff --git a/tests/elfs/struct_func_pointer.rs b/tests/elfs/struct_func_pointer.rs new file mode 100644 index 00000000..766e36ea --- /dev/null +++ b/tests/elfs/struct_func_pointer.rs @@ -0,0 +1,16 @@ +struct PubkeyLutEntry { + _fp: fn(u8) -> u8, + key: u64, +} + +fn f1(a: u8) -> u8 { + return a + 1; +} + +#[link_section = ".data.rel.ro"] +static E1: PubkeyLutEntry = PubkeyLutEntry { _fp: f1, key: 0x0102030405060708 }; + +#[no_mangle] +pub fn entrypoint() -> u64 { + return E1.key; +} diff --git a/tests/elfs/struct_func_pointer.so b/tests/elfs/struct_func_pointer.so index 5655571f..ded65ef0 100755 Binary files a/tests/elfs/struct_func_pointer.so and b/tests/elfs/struct_func_pointer.so differ diff --git a/tests/elfs/syscall_reloc_64_32.rs b/tests/elfs/syscall_reloc_64_32.rs new file mode 100644 index 00000000..0681d26a --- /dev/null +++ b/tests/elfs/syscall_reloc_64_32.rs @@ -0,0 +1,11 @@ +mod syscalls { + extern "C" { + pub fn log(str: *const u8, len: u64); + } +} + +#[no_mangle] +pub fn entrypoint() -> u64 { + unsafe { syscalls::log(b"foo\n".as_ptr(), 4); } + return 0; +} diff --git a/tests/elfs/syscall_reloc_64_32.so b/tests/elfs/syscall_reloc_64_32.so new file mode 100755 index 00000000..c765a7cc Binary files /dev/null and b/tests/elfs/syscall_reloc_64_32.so differ diff --git a/tests/elfs/syscall_static.c b/tests/elfs/syscall_static.c deleted file mode 100644 index 58f2a4b9..00000000 --- a/tests/elfs/syscall_static.c +++ /dev/null @@ -1,7 +0,0 @@ -#include "syscalls.h" - -extern uint64_t entrypoint(const uint8_t *input) { - log("foo\n", 4); - - return 0; -} diff --git a/tests/elfs/syscall_static.rs b/tests/elfs/syscall_static.rs new file mode 100644 index 00000000..f4fd29d8 --- /dev/null +++ b/tests/elfs/syscall_static.rs @@ -0,0 +1,7 @@ +mod syscalls; + +#[no_mangle] +pub fn entrypoint() -> u64 { + unsafe { syscalls::log(b"foo\n".as_ptr(), 4); } + return 0; +} diff --git a/tests/elfs/syscall_static.so b/tests/elfs/syscall_static.so index 31582f76..8a0ccadc 100755 Binary files a/tests/elfs/syscall_static.so and b/tests/elfs/syscall_static.so differ diff --git a/tests/elfs/syscall_static_unknown.c b/tests/elfs/syscall_static_unknown.c deleted file mode 100644 index 82fc36ec..00000000 --- a/tests/elfs/syscall_static_unknown.c +++ /dev/null @@ -1,10 +0,0 @@ -typedef unsigned long int uint64_t; -typedef unsigned char uint8_t; - -static void (*i_dont_exist)() = (void *) 42; - -extern uint64_t entrypoint(const uint8_t *input) { - i_dont_exist(); - - return 0; -} diff --git a/tests/elfs/syscalls.h b/tests/elfs/syscalls.h deleted file mode 100644 index e3b33159..00000000 --- a/tests/elfs/syscalls.h +++ /dev/null @@ -1,5 +0,0 @@ -typedef unsigned char uint8_t; -typedef unsigned long int uint64_t; - -static void (*log)(const char*, uint64_t) = (void *) 1811268606; -static void (*log_64)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t) = (void *) 1883515721; diff --git a/tests/elfs/syscalls.rs b/tests/elfs/syscalls.rs new file mode 100644 index 00000000..544903e4 --- /dev/null +++ b/tests/elfs/syscalls.rs @@ -0,0 +1,72 @@ +pub const fn sys_hash(name: &str) -> usize { + murmur3_32(name.as_bytes(), 0) as usize +} + +const fn murmur3_32(buf: &[u8], seed: u32) -> u32 { + const fn pre_mix(buf: [u8; 4]) -> u32 { + u32::from_le_bytes(buf) + .wrapping_mul(0xcc9e2d51) + .rotate_left(15) + .wrapping_mul(0x1b873593) + } + + let mut hash = seed; + + let mut i = 0; + while i < buf.len() / 4 { + let buf = [buf[i * 4], buf[i * 4 + 1], buf[i * 4 + 2], buf[i * 4 + 3]]; + hash ^= pre_mix(buf); + hash = hash.rotate_left(13); + hash = hash.wrapping_mul(5).wrapping_add(0xe6546b64); + + i += 1; + } + + match buf.len() % 4 { + 0 => {} + 1 => { + hash = hash ^ pre_mix([buf[i * 4], 0, 0, 0]); + } + 2 => { + hash = hash ^ pre_mix([buf[i * 4], buf[i * 4 + 1], 0, 0]); + } + 3 => { + hash = hash ^ pre_mix([buf[i * 4], buf[i * 4 + 1], buf[i * 4 + 2], 0]); + } + _ => { /* unreachable!() */ } + } + + hash = hash ^ buf.len() as u32; + hash = hash ^ (hash.wrapping_shr(16)); + hash = hash.wrapping_mul(0x85ebca6b); + hash = hash ^ (hash.wrapping_shr(13)); + hash = hash.wrapping_mul(0xc2b2ae35); + hash = hash ^ (hash.wrapping_shr(16)); + + hash +} + +#[cfg(target_feature = "static-syscalls")] +macro_rules! define_syscall { + (fn $name:ident($($arg:ident: $typ:ty),*) -> $ret:ty) => { + #[allow(dead_code)] + #[inline] + pub unsafe fn $name($($arg: $typ),*) -> $ret { + // this enum is used to force the hash to be computed in a const context + #[repr(usize)] + enum Syscall { + Code = sys_hash(stringify!($name)), + } + + let syscall: extern "C" fn($($arg: $typ),*) -> $ret = core::mem::transmute(Syscall::Code); + syscall($($arg),*) + } + + }; + (fn $name:ident($($arg:ident: $typ:ty),*)) => { + define_syscall!(fn $name($($arg: $typ),*) -> ()); + } +} + +define_syscall!(fn log(message: *const u8, len: u64)); +define_syscall!(fn log_64(arg1: u64, arg2: u64, arg3: u64, arg4: u64, arg5: u64)); diff --git a/tests/elfs/unresolved_syscall.c b/tests/elfs/unresolved_syscall.c deleted file mode 100644 index 33f61048..00000000 --- a/tests/elfs/unresolved_syscall.c +++ /dev/null @@ -1,15 +0,0 @@ -/** - * @brief test program used to test unresolved syscall handling - */ - -typedef unsigned char uint8_t; -typedef unsigned long int uint64_t; - -extern void log(const char*, uint64_t); -extern void log_64(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t); - -extern uint64_t entrypoint(const uint8_t *input) { - log(__func__, sizeof(__func__)); - log_64(1, 2, 3, 4, 5); - return 0; -} diff --git a/tests/elfs/unresolved_syscall.so b/tests/elfs/unresolved_syscall.so deleted file mode 100755 index bb949a07..00000000 Binary files a/tests/elfs/unresolved_syscall.so and /dev/null differ diff --git a/tests/elfs/writable_data_section.c b/tests/elfs/writable_data_section.c deleted file mode 100644 index 44b6978f..00000000 --- a/tests/elfs/writable_data_section.c +++ /dev/null @@ -1,9 +0,0 @@ -typedef unsigned long int uint64_t; -typedef unsigned char uint8_t; - -int val = 42; - -extern uint64_t entrypoint(const uint8_t *input) { - val = 43; - return 0; -} diff --git a/tests/elfs/writable_data_section.so b/tests/elfs/writable_data_section.so deleted file mode 100755 index 8b5f92f1..00000000 Binary files a/tests/elfs/writable_data_section.so and /dev/null differ diff --git a/tests/execution.rs b/tests/execution.rs index 75181098..39beb207 100644 --- a/tests/execution.rs +++ b/tests/execution.rs @@ -2592,37 +2592,38 @@ fn test_err_mem_access_out_of_bound() { #[test] fn test_relative_call() { test_interpreter_and_jit_elf!( - "tests/elfs/relative_call_sbpfv1.so", + "tests/elfs/relative_call.so", [1], - ( - "log" => syscalls::bpf_syscall_string, - ), - TestContextObject::new(23), - ProgramResult::Ok(4), + (), + TestContextObject::new(18), + ProgramResult::Ok(3), ); } #[test] fn test_bpf_to_bpf_scratch_registers() { - test_interpreter_and_jit_elf!( - "tests/elfs/scratch_registers.so", - [1], - ( - "log_64" => syscalls::bpf_syscall_u64, - ), - TestContextObject::new(40), - ProgramResult::Ok(112), - ); -} - -#[test] -fn test_bpf_to_bpf_pass_stack_reference() { - test_interpreter_and_jit_elf!( - "tests/elfs/pass_stack_reference.so", + test_interpreter_and_jit_asm!( + " + mov64 r6, 0x11 + mov64 r7, 0x22 + mov64 r8, 0x44 + mov64 r9, 0x88 + call function_foo + mov64 r0, r6 + add64 r0, r7 + add64 r0, r8 + add64 r0, r9 + exit + function_foo: + mov64 r6, 0x00 + mov64 r7, 0x00 + mov64 r8, 0x00 + mov64 r9, 0x00 + exit", [], (), - TestContextObject::new(37), - ProgramResult::Ok(42), + TestContextObject::new(15), + ProgramResult::Ok(0xFF), ); } @@ -2809,33 +2810,41 @@ fn test_err_dynamic_jmp_lddw() { #[test] fn test_bpf_to_bpf_depth() { - let config = Config::default(); - for i in 0..config.max_call_depth { - test_interpreter_and_jit_elf!( - "tests/elfs/multiple_file.so", - config, - [i as u8], - ( - "log" => syscalls::bpf_syscall_string, - ), - TestContextObject::new(if i == 0 { 4 } else { 3 + 10 * i as u64 }), - ProgramResult::Ok(0), - ); - } -} - -#[test] -fn test_err_bpf_to_bpf_too_deep() { - let config = Config::default(); - test_interpreter_and_jit_elf!( - "tests/elfs/multiple_file.so", - config, - [config.max_call_depth as u8], - ( - "log" => syscalls::bpf_syscall_string, - ), - TestContextObject::new(176), - ProgramResult::Err(Box::new(EbpfError::CallDepthExceeded(55, config.max_call_depth))), + test_interpreter_and_jit_asm!( + " + ldxb r1, [r1] + add64 r1, -2 + call function_foo + exit + function_foo: + jeq r1, 0, +2 + add64 r1, -1 + call function_foo + exit", + [Config::default().max_call_depth as u8], + (), + TestContextObject::new(78), + ProgramResult::Ok(0), + ); + // The instruction count is lower here because all the `exit`s never run + test_interpreter_and_jit_asm!( + " + ldxb r1, [r1] + add64 r1, -2 + call function_foo + exit + function_foo: + jeq r1, 0, +2 + add64 r1, -1 + call function_foo + exit", + [Config::default().max_call_depth as u8 + 1], + (), + TestContextObject::new(60), + ProgramResult::Err(Box::new(EbpfError::CallDepthExceeded( + 35, + Config::default().max_call_depth + ))), ); } @@ -3054,80 +3063,6 @@ fn test_nested_vm_syscall() { assert_error!(result, "CallDepthExceeded(33, 0)"); } -// Elf - -#[test] -fn test_load_elf() { - test_interpreter_and_jit_elf!( - "tests/elfs/noop.so", - [], - ( - "log" => syscalls::bpf_syscall_string, - "log_64" => syscalls::bpf_syscall_u64, - ), - TestContextObject::new(11), - ProgramResult::Ok(0), - ); -} - -#[test] -fn test_load_elf_empty_noro() { - test_interpreter_and_jit_elf!( - "tests/elfs/noro.so", - [], - ( - "log_64" => syscalls::bpf_syscall_u64, - ), - TestContextObject::new(8), - ProgramResult::Ok(0), - ); -} - -#[test] -fn test_load_elf_empty_rodata() { - test_interpreter_and_jit_elf!( - "tests/elfs/empty_rodata.so", - [], - ( - "log_64" => syscalls::bpf_syscall_u64, - ), - TestContextObject::new(8), - ProgramResult::Ok(0), - ); -} - -#[test] -fn test_load_elf_rodata() { - let config = Config { - optimize_rodata: true, - ..Config::default() - }; - test_interpreter_and_jit_elf!( - "tests/elfs/rodata.so", - config, - [], - (), - TestContextObject::new(3), - ProgramResult::Ok(42), - ); -} - -#[test] -fn test_load_elf_rodata_sbpfv1() { - let config = Config { - optimize_rodata: false, - ..Config::default() - }; - test_interpreter_and_jit_elf!( - "tests/elfs/rodata_sbpfv1.so", - config, - [], - (), - TestContextObject::new(3), - ProgramResult::Ok(42), - ); -} - // Instruction Meter Limit #[test] @@ -3420,18 +3355,15 @@ fn test_err_call_unresolved() { } #[test] -fn test_err_unresolved_elf() { - let mut loader = BuiltinProgram::new_loader(Config { - reject_broken_elfs: true, - ..Config::default() - }); - test_interpreter_and_jit!(register, loader, "log" => syscalls::bpf_syscall_string); - let mut file = File::open("tests/elfs/unresolved_syscall.so").unwrap(); - let mut elf = Vec::new(); - file.read_to_end(&mut elf).unwrap(); - assert_error!( - Executable::::from_elf(&elf, Arc::new(loader)), - "UnresolvedSymbol(\"log_64\", 550, 4168)" +fn test_syscall_reloc_64_32() { + test_interpreter_and_jit_elf!( + "tests/elfs/syscall_reloc_64_32.so", + [], + ( + "log" => syscalls::bpf_syscall_string, + ), + TestContextObject::new(5), + ProgramResult::Ok(0), ); } @@ -3449,19 +3381,28 @@ fn test_syscall_static() { } #[test] -fn test_syscall_unknown_static() { - // Check that unknown static syscalls result in UnsupportedInstruction. - // - // See also elf::test::test_static_syscall_disabled for the corresponding - // check with config.syscalls_static=false. +fn test_err_unresolved_syscall_reloc_64_32() { + let loader = BuiltinProgram::new_loader(Config { + reject_broken_elfs: true, + ..Config::default() + }); + let mut file = File::open("tests/elfs/syscall_reloc_64_32.so").unwrap(); + let mut elf = Vec::new(); + file.read_to_end(&mut elf).unwrap(); + assert_error!( + Executable::::from_elf(&elf, Arc::new(loader)), + "UnresolvedSymbol(\"log\", 68, 312)" + ); +} + +#[test] +fn test_err_unresolved_syscall_static() { test_interpreter_and_jit_elf!( - "tests/elfs/syscall_static_unknown.so", + "tests/elfs/syscall_static.so", [], - ( - "log" => syscalls::bpf_syscall_string, - ), - TestContextObject::new(1), - ProgramResult::Err(Box::new(EbpfError::UnsupportedInstruction(29))), + (), + TestContextObject::new(3), + ProgramResult::Err(Box::new(EbpfError::UnsupportedInstruction(32))), ); } @@ -3469,13 +3410,13 @@ fn test_syscall_unknown_static() { fn test_reloc_64_64_sbpfv1() { // Tests the correctness of R_BPF_64_64 relocations. The program returns the // address of the entrypoint. - // [ 1] .text PROGBITS 00000000000000e8 0000e8 000018 00 AX 0 0 8 + // [ 1] .text PROGBITS 0000000000000120 000120 000018 00 AX 0 0 8 test_interpreter_and_jit_elf!( "tests/elfs/reloc_64_64_sbpfv1.so", [], (), TestContextObject::new(2), - ProgramResult::Ok(ebpf::MM_PROGRAM_START + 0xe8), + ProgramResult::Ok(ebpf::MM_PROGRAM_START + 0x120), ); } @@ -3497,14 +3438,14 @@ fn test_reloc_64_64() { fn test_reloc_64_relative_sbpfv1() { // Tests the correctness of R_BPF_64_RELATIVE relocations. The program // returns the address of the first .rodata byte. - // [ 1] .text PROGBITS 00000000000000e8 0000e8 000018 00 AX 0 0 8 - // [ 2] .rodata PROGBITS 0000000000000100 000100 00000b 01 AMS 0 0 1 + // [ 1] .text PROGBITS 0000000000000120 000120 000018 00 AX 0 0 8 + // [ 2] .rodata PROGBITS 0000000000000138 000138 00000a 01 AMS 0 0 1 test_interpreter_and_jit_elf!( "tests/elfs/reloc_64_relative_sbpfv1.so", [], (), TestContextObject::new(2), - ProgramResult::Ok(ebpf::MM_PROGRAM_START + 0x100), + ProgramResult::Ok(ebpf::MM_PROGRAM_START + 0x138), ); } @@ -3583,6 +3524,38 @@ fn test_reloc_64_relative_data_sbpfv1() { ); } +#[test] +fn test_load_elf_rodata() { + let config = Config { + optimize_rodata: true, + ..Config::default() + }; + test_interpreter_and_jit_elf!( + "tests/elfs/rodata_section.so", + config, + [], + (), + TestContextObject::new(3), + ProgramResult::Ok(42), + ); +} + +#[test] +fn test_load_elf_rodata_sbpfv1() { + let config = Config { + optimize_rodata: false, + ..Config::default() + }; + test_interpreter_and_jit_elf!( + "tests/elfs/rodata_section_sbpfv1.so", + config, + [], + (), + TestContextObject::new(3), + ProgramResult::Ok(42), + ); +} + // Programs #[test] @@ -3800,7 +3773,7 @@ fn test_struct_func_pointer() { "tests/elfs/struct_func_pointer.so", [], (), - TestContextObject::new(3), + TestContextObject::new(2), ProgramResult::Ok(0x102030405060708), ); }