Skip to content

Commit

Permalink
Fix - callx (#583)
Browse files Browse the repository at this point in the history
* adds test

* fix callx
  • Loading branch information
Lichtso authored Aug 16, 2024
1 parent c72113b commit 2d38c95
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 16 deletions.
5 changes: 1 addition & 4 deletions src/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -449,10 +449,7 @@ impl<'a, 'b, C: ContextObject> Interpreter<'a, 'b, C> {
if !self.push_frame(config) {
return false;
}
if target_pc < self.program_vm_addr {
throw_error!(self, EbpfError::CallOutsideTextSegment);
}
check_pc!(self, next_pc, (target_pc - self.program_vm_addr) / ebpf::INSN_SIZE as u64);
check_pc!(self, next_pc, target_pc.wrapping_sub(self.program_vm_addr) / ebpf::INSN_SIZE as u64);
if self.executable.get_sbpf_version().static_syscalls() && self.executable.get_function_registry().lookup_by_key(next_pc as u32).is_none() {
self.vm.due_insn_count += 1;
self.reg[11] = next_pc;
Expand Down
17 changes: 6 additions & 11 deletions src/jit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1463,21 +1463,16 @@ impl<'a, C: ContextObject> JitCompiler<'a, C> {

// Routine for emit_internal_call(Value::Register())
self.set_anchor(ANCHOR_ANCHOR_INTERNAL_FUNCTION_CALL_REG);
// Calculate offset relative to instruction_addresses
self.emit_ins(X86Instruction::load_immediate(OperandSize::S64, REGISTER_MAP[FRAME_PTR_REG], self.program_vm_addr as i64));
self.emit_ins(X86Instruction::alu(OperandSize::S64, 0x29, REGISTER_MAP[FRAME_PTR_REG], REGISTER_MAP[0], 0, None)); // RAX -= self.program_vm_addr;
// Force alignment of RAX
self.emit_ins(X86Instruction::alu(OperandSize::S64, 0x81, 4, REGISTER_MAP[0], !(INSN_SIZE as i64 - 1), None)); // RAX &= !(INSN_SIZE - 1);
// Upper bound check
// if(RAX >= self.program_vm_addr + number_of_instructions * INSN_SIZE) throw CALL_OUTSIDE_TEXT_SEGMENT;
// Bound check
// if(RAX >= number_of_instructions * INSN_SIZE) throw CALL_OUTSIDE_TEXT_SEGMENT;
let number_of_instructions = self.result.pc_section.len();
self.emit_ins(X86Instruction::load_immediate(OperandSize::S64, REGISTER_MAP[FRAME_PTR_REG], self.program_vm_addr as i64 + (number_of_instructions * INSN_SIZE) as i64));
self.emit_ins(X86Instruction::cmp(OperandSize::S64, REGISTER_MAP[FRAME_PTR_REG], REGISTER_MAP[0], None));
self.emit_ins(X86Instruction::cmp_immediate(OperandSize::S64, REGISTER_MAP[0], (number_of_instructions * INSN_SIZE) as i64, None));
self.emit_ins(X86Instruction::conditional_jump_immediate(0x83, self.relative_to_anchor(ANCHOR_CALL_OUTSIDE_TEXT_SEGMENT, 6)));
// Lower bound check
// if(RAX < self.program_vm_addr) throw CALL_OUTSIDE_TEXT_SEGMENT;
self.emit_ins(X86Instruction::load_immediate(OperandSize::S64, REGISTER_MAP[FRAME_PTR_REG], self.program_vm_addr as i64));
self.emit_ins(X86Instruction::cmp(OperandSize::S64, REGISTER_MAP[FRAME_PTR_REG], REGISTER_MAP[0], None));
self.emit_ins(X86Instruction::conditional_jump_immediate(0x82, self.relative_to_anchor(ANCHOR_CALL_OUTSIDE_TEXT_SEGMENT, 6)));
// Calculate offset relative to instruction_addresses
self.emit_ins(X86Instruction::alu(OperandSize::S64, 0x29, REGISTER_MAP[FRAME_PTR_REG], REGISTER_MAP[0], 0, None)); // RAX -= self.program_vm_addr;
// Calculate the target_pc (dst / INSN_SIZE) to update REGISTER_INSTRUCTION_METER
// and as target pc for potential ANCHOR_CALL_UNSUPPORTED_INSTRUCTION
let shift_amount = INSN_SIZE.trailing_zeros();
Expand Down
12 changes: 12 additions & 0 deletions tests/elfs/callx_unaligned.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#![feature(asm_experimental_arch)]

#[no_mangle]
pub fn entrypoint() {
unsafe {
std::arch::asm!("
rsh64 r1, 2
or64 r1, 0x129
callx r1
");
}
}
Binary file added tests/elfs/callx_unaligned.so
Binary file not shown.
5 changes: 4 additions & 1 deletion tests/elfs/elfs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Requires Latest release of Solana's custom LLVM
# https://github.com/solana-labs/platform-tools/releases

TOOLCHAIN=../../../solana/sdk/sbf/dependencies/sbf-tools
TOOLCHAIN=../../../agave/sdk/sbf/dependencies/platform-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"
Expand Down Expand Up @@ -56,4 +56,7 @@ $LD_V1 -o reloc_64_relative_sbpfv1.so reloc_64_relative.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

# $RC_V1 -o callx_unaligned.o callx_unaligned.rs
# $LD_V1 -o callx_unaligned.so callx_unaligned.o

rm *.o
11 changes: 11 additions & 0 deletions tests/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2320,6 +2320,17 @@ fn test_err_callx_oob_high() {
);
}

#[test]
fn test_callx_unaligned_text_section() {
test_interpreter_and_jit_elf!(
"tests/elfs/callx_unaligned.so",
[],
(),
TestContextObject::new(129),
ProgramResult::Err(EbpfError::CallDepthExceeded),
);
}

#[test]
fn test_bpf_to_bpf_depth() {
for max_call_depth in [20usize, Config::default().max_call_depth] {
Expand Down

0 comments on commit 2d38c95

Please sign in to comment.