Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

elf: add support for rodata sections already aligned to MM_PROGRAM_START #301

Merged
merged 1 commit into from
Apr 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
415 changes: 327 additions & 88 deletions src/elf.rs

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,9 @@ pub struct Config {
pub optimize_rodata: bool,
/// Support syscalls via pseudo calls (insn.src = 0)
pub static_syscalls: bool,
/// Allow sh_addr != sh_offset in elf sections. Used in SBFv2 to align
/// section vaddrs to MM_PROGRAM_START.
pub enable_elf_vaddr: bool,
}

impl Config {
Expand Down Expand Up @@ -264,6 +267,7 @@ impl Default for Config {
enable_sdiv: true,
optimize_rodata: true,
static_syscalls: true,
enable_elf_vaddr: true,
}
}
}
Expand Down
42 changes: 35 additions & 7 deletions tests/elfs/elfs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,33 @@ rm syscall.o
"$LLVM_DIR"ld.lld -z notext -shared --Bdynamic -entry entrypoint -o relative_call.so relative_call.o
rm relative_call.o

"$LLVM_DIR"clang -Werror -target bpf -O2 -fno-builtin -fPIC -o reloc.o -c reloc.c
"$LLVM_DIR"ld.lld -script elf.ld -z notext -shared --Bdynamic -entry entrypoint -o reloc.so reloc.o
rm reloc.o
"$LLVM_DIR"clang -Werror -target bpf -O2 -fno-builtin -fPIC -o reloc_64_64.o -c reloc_64_64.c
"$LLVM_DIR"ld.lld -script elf.ld -z notext -shared --Bdynamic -entry entrypoint -o reloc_64_64.so reloc_64_64.o
rm reloc_64_64.o

"$LLVM_DIR"clang -Werror -target sbf -mcpu=sbfv2 -O2 -fno-builtin -fPIC -o reloc_64_64_high_vaddr.o -c reloc_64_64.c
"$LLVM_DIR"ld.lld -z notext -shared --Bdynamic -entry entrypoint --nmagic --section-start=.text=0x100000000 -o reloc_64_64_high_vaddr.so reloc_64_64_high_vaddr.o
rm reloc_64_64_high_vaddr.o

"$LLVM_DIR"clang -Werror -target bpf -O2 -fno-builtin -fPIC -o reloc_64_relative.o -c reloc_64_relative.c
"$LLVM_DIR"ld.lld -script elf.ld -z notext -shared --Bdynamic -entry entrypoint -o reloc_64_relative.so reloc_64_relative.o
rm reloc_64_relative.o

"$LLVM_DIR"clang -Werror -target sbf -mcpu=sbfv2 -O2 -fno-builtin -fPIC -o reloc_64_relative_high_vaddr.o -c reloc_64_relative.c
"$LLVM_DIR"ld.lld -script elf.ld -z notext -shared --Bdynamic -entry entrypoint --section-start=.text=0x100000000 -o reloc_64_relative_high_vaddr.so reloc_64_relative_high_vaddr.o
rm reloc_64_relative_high_vaddr.o

"$LLVM_DIR"clang -Werror -target sbf -O2 -mcpu=sbfv2 -fno-builtin -fPIC -o reloc_64_relative_data.o -c reloc_64_relative_data.c
"$LLVM_DIR"ld.lld -script elf.ld -z notext -shared --Bdynamic -entry entrypoint -o reloc_64_relative_data.so reloc_64_relative_data.o
rm reloc_64_relative_data.o

"$LLVM_DIR"clang -Werror -target sbf -mcpu=sbfv2 -O2 -fno-builtin -fPIC -o reloc_64_relative_data_high_vaddr.o -c reloc_64_relative_data.c
"$LLVM_DIR"ld.lld -script elf.ld -z notext -shared --Bdynamic -entry entrypoint --section-start=.text=0x100000000 -o reloc_64_relative_data_high_vaddr.so reloc_64_relative_data_high_vaddr.o
rm reloc_64_relative_data_high_vaddr.o

"$LLVM_DIR"clang -Werror -target sbf -O2 -fno-builtin -fPIC -o reloc_64_relative_data_pre_sbfv2.o -c reloc_64_relative_data.c
"$LLVM_DIR"ld.lld -script elf.ld -z notext -shared --Bdynamic -entry entrypoint -o reloc_64_relative_data_pre_sbfv2.so reloc_64_relative_data_pre_sbfv2.o
rm reloc_64_relative_data_pre_sbfv2.o

"$LLVM_DIR"clang -Werror -target bpf -O2 -fno-builtin -fPIC -o scratch_registers.o -c scratch_registers.c
"$LLVM_DIR"ld.lld -z notext -shared --Bdynamic -entry entrypoint -o scratch_registers.so scratch_registers.o
Expand All @@ -55,10 +79,14 @@ rm bss_section.o
"$LLVM_DIR"ld.lld -z notext -shared --Bdynamic -entry entrypoint --script elf.ld -o rodata.so rodata.o
rm rodata.o

"$LLVM_DIR"clang -Werror -target bpf -O2 -fno-builtin -fPIC -o syscall_static.o -c syscall_static.c
"$LLVM_DIR"ld.lld -z notext -shared --Bdynamic -entry entrypoint --script elf.ld -o syscall_static.so syscall_static.o
rm syscall_static.o
"$LLVM_DIR"clang -Werror -target sbf -mcpu=sbfv2 -O2 -fno-builtin -fPIC -o rodata_high_vaddr.o -c rodata.c
"$LLVM_DIR"ld.lld -z notext -shared --Bdynamic -entry entrypoint --nmagic --section-start=.text=0x100000000 --section-start=.rodata=0x100000020 -o rodata_high_vaddr.so rodata_high_vaddr.o
rm rodata_high_vaddr.o

"$LLVM_DIR"clang -Werror -target bpf -O2 -fno-builtin -fPIC -o syscall_static_unknown.o -c syscall_static_unknown.c
"$LLVM_DIR"ld.lld -z notext -shared --Bdynamic -entry entrypoint --script elf.ld -o syscall_static_unknown.so syscall_static_unknown.o
rm syscall_static_unknown.o
rm syscall_static_unknown.o

"$LLVM_DIR"clang -Werror -target bpf -O2 -fno-builtin -fPIC -o syscall_static.o -c syscall_static.c
"$LLVM_DIR"ld.lld -z notext -shared --Bdynamic -entry entrypoint --script elf.ld -o syscall_static.so syscall_static.o
rm syscall_static.o
Binary file removed tests/elfs/reloc.so
Binary file not shown.
File renamed without changes.
Binary file added tests/elfs/reloc_64_64.so
Binary file not shown.
Binary file added tests/elfs/reloc_64_64_high_vaddr.so
Binary file not shown.
10 changes: 10 additions & 0 deletions tests/elfs/reloc_64_relative.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* @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__;
}
Binary file added tests/elfs/reloc_64_relative.so
Binary file not shown.
13 changes: 13 additions & 0 deletions tests/elfs/reloc_64_relative_data.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/**
* @brief a program to test R_BPF_64_RELATIVE relocation handling
*/

typedef unsigned long int uint64_t;
typedef unsigned char uint8_t;

// this will store __FILE__ and generate a relocation for FILE to refer to it
volatile const uint64_t FILE = (uint64_t) __FILE__;

extern uint64_t entrypoint(const uint8_t *input) {
return FILE;
}
Binary file added tests/elfs/reloc_64_relative_data.so
Binary file not shown.
Binary file added tests/elfs/reloc_64_relative_data_high_vaddr.so
Binary file not shown.
Binary file added tests/elfs/reloc_64_relative_data_pre_sbfv2.so
Binary file not shown.
Binary file added tests/elfs/reloc_64_relative_high_vaddr.so
Binary file not shown.
Binary file added tests/elfs/rodata_high_vaddr.so
Binary file not shown.
136 changes: 136 additions & 0 deletions tests/ubpf_execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3562,6 +3562,18 @@ fn test_load_elf_rodata() {
}
}

#[test]
fn test_load_elf_rodata_high_vaddr() {
test_interpreter_and_jit_elf!(
"tests/elfs/rodata_high_vaddr.so",
[1],
(),
0,
{ |_vm, res: Result| { res.unwrap() == 42 } },
3
);
}

#[test]
fn test_custom_entrypoint() {
let mut file = File::open("tests/elfs/unresolved_syscall.so").expect("file open failed");
Expand Down Expand Up @@ -4049,6 +4061,130 @@ fn test_syscall_unknown_static() {
);
}

#[test]
fn test_reloc_64_64() {
// 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
test_interpreter_and_jit_elf!(
"tests/elfs/reloc_64_64.so",
[],
(),
0,
{ |_vm, res: Result| { res.unwrap() == ebpf::MM_PROGRAM_START + 0xe8 } },
2
);
}

#[test]
fn test_reloc_64_64_high_vaddr() {
// Same as test_reloc_64_64, but with .text already alinged to
// MM_PROGRAM_START by the linker
test_interpreter_and_jit_elf!(
"tests/elfs/reloc_64_64_high_vaddr.so",
[],
(),
0,
{ |_vm, res: Result| { res.unwrap() == ebpf::MM_PROGRAM_START } },
2
);
}

#[test]
fn test_reloc_64_relative() {
// 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
test_interpreter_and_jit_elf!(
"tests/elfs/reloc_64_relative.so",
[],
(),
0,
{ |_vm, res: Result| { res.unwrap() == ebpf::MM_PROGRAM_START + 0x100 } },
2
);
}

#[test]
fn test_reloc_64_relative_high_vaddr() {
// Same as test_reloc_64_relative, but with .text placed already within
// MM_PROGRAM_START by the linker
// [ 1] .text PROGBITS 0000000100000000 001000 000018 00 AX 0 0 8
// [ 2] .rodata PROGBITS 0000000100000018 001018 00000b 01 AMS 0 0 1
test_interpreter_and_jit_elf!(
"tests/elfs/reloc_64_relative_high_vaddr.so",
[],
(),
0,
{ |_vm, res: Result| { res.unwrap() == ebpf::MM_PROGRAM_START + 0x18 } },
2
);
}

#[test]
fn test_reloc_64_relative_data() {
// Tests the correctness of R_BPF_64_RELATIVE relocations in sections other
// than .text. The program returns the address of the first .rodata byte.
// [ 1] .text PROGBITS 00000000000000e8 0000e8 000020 00 AX 0 0 8
// [ 2] .rodata PROGBITS 0000000000000108 000108 000019 01 AMS 0 0 1
//
// 00000000000001f8 <FILE>:
// 63: 08 01 00 00 00 00 00 00
test_interpreter_and_jit_elf!(
"tests/elfs/reloc_64_relative_data.so",
[],
(),
0,
{ |_vm, res: Result| { res.unwrap() == ebpf::MM_PROGRAM_START + 0x108 } },
3
);
}

#[test]
fn test_reloc_64_relative_data_high_vaddr() {
// Same as test_reloc_64_relative_data, but with rodata already placed
// within MM_PROGRAM_START by the linker
// [ 1] .text PROGBITS 0000000100000000 001000 000020 00 AX 0 0 8
// [ 2] .rodata PROGBITS 0000000100000020 001020 000019 01 AMS 0 0 1
//
// 0000000100000110 <FILE>:
// 536870946: 20 00 00 00 01 00 00 00
test_interpreter_and_jit_elf!(
"tests/elfs/reloc_64_relative_data_high_vaddr.so",
[],
(),
0,
{ |_vm, res: Result| { res.unwrap() == ebpf::MM_PROGRAM_START + 0x20 } },
3
);
}

#[test]
fn test_reloc_64_relative_data_pre_sbfv2() {
// Before https://github.com/solana-labs/llvm-project/pull/35, we used to
// generate invalid R_BPF_64_RELATIVE relocations in sections other than
// .text.
//
// This test checks that the old behaviour is maintained for backwards
// compatibility when dealing with non-sbfv2 files. See also Elf::relocate().
//
// The program returns the address of the first .rodata byte.
// [ 1] .text PROGBITS 00000000000000e8 0000e8 000020 00 AX 0 0 8
// [ 2] .rodata PROGBITS 0000000000000108 000108 000019 01 AMS 0 0 1
//
// 00000000000001f8 <FILE>:
// 63: 00 00 00 00 08 01 00 00
test_interpreter_and_jit_elf!(
"tests/elfs/reloc_64_relative_data_pre_sbfv2.so",
[],
(),
0,
{ |_vm, res: Result| { res.unwrap() == ebpf::MM_PROGRAM_START + 0x108 } },
3
);
}

// Programs

#[test]
Expand Down