Skip to content

Commit

Permalink
Rewrite of C ELF tests to Rust or ASM.
Browse files Browse the repository at this point in the history
  • Loading branch information
Lichtso committed Jul 12, 2023
1 parent a2ea2de commit 01dee12
Show file tree
Hide file tree
Showing 57 changed files with 370 additions and 555 deletions.
23 changes: 5 additions & 18 deletions benches/elf_loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,13 @@ use test::Bencher;

fn loader() -> Arc<BuiltinProgram<TestContextObject>> {
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();
Expand All @@ -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::<TautologyVerifier, TestContextObject>::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();
Expand Down
27 changes: 14 additions & 13 deletions src/elf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down Expand Up @@ -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");
Expand All @@ -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.
Expand All @@ -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");
Expand Down Expand Up @@ -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");
}

Expand All @@ -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");
}
}
9 changes: 0 additions & 9 deletions tests/elfs/bss_section.c

This file was deleted.

7 changes: 7 additions & 0 deletions tests/elfs/bss_section.rs
Original file line number Diff line number Diff line change
@@ -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;
}
Binary file modified tests/elfs/bss_section.so
Binary file not shown.
7 changes: 7 additions & 0 deletions tests/elfs/data_section.rs
Original file line number Diff line number Diff line change
@@ -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;
}
Binary file not shown.
20 changes: 13 additions & 7 deletions tests/elfs/elf.ld
Original file line number Diff line number Diff line change
Expand Up @@ -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*)
}
}
155 changes: 56 additions & 99 deletions tests/elfs/elfs.sh
Original file line number Diff line number Diff line change
@@ -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
10 changes: 0 additions & 10 deletions tests/elfs/empty_rodata.c

This file was deleted.

22 changes: 0 additions & 22 deletions tests/elfs/entrypoint.c

This file was deleted.

14 changes: 0 additions & 14 deletions tests/elfs/multiple_file.c

This file was deleted.

8 changes: 0 additions & 8 deletions tests/elfs/multiple_file.h

This file was deleted.

Binary file removed tests/elfs/multiple_file.so
Binary file not shown.
Loading

0 comments on commit 01dee12

Please sign in to comment.