Skip to content
This repository was archived by the owner on Jan 10, 2025. It is now read-only.

Commit c16589f

Browse files
authored
Stops clobbering FRAME_PTR_REG in ANCHOR_INTERNAL_FUNCTION_CALL_REG. (#637)
1 parent a8247dd commit c16589f

File tree

1 file changed

+20
-24
lines changed

1 file changed

+20
-24
lines changed

src/jit.rs

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1114,8 +1114,11 @@ impl<'a, C: ContextObject> JitCompiler<'a, C> {
11141114

11151115
match dst {
11161116
Value::Register(reg) => {
1117-
// Move guest_target_address into REGISTER_MAP[FRAME_PTR_REG]
1118-
self.emit_ins(X86Instruction::mov(OperandSize::S64, reg, REGISTER_MAP[FRAME_PTR_REG]));
1117+
// REGISTER_SCRATCH contains self.pc, and we must store it for proper error handling.
1118+
// We can discard the value if callx succeeds, so we are not incrementing the stack pointer (RSP).
1119+
self.emit_ins(X86Instruction::store(OperandSize::S64, REGISTER_SCRATCH, RSP, X86IndirectAccess::OffsetIndexShift(-24, RSP, 0)));
1120+
// Move guest_target_address into REGISTER_SCRATCH
1121+
self.emit_ins(X86Instruction::mov(OperandSize::S64, reg, REGISTER_SCRATCH));
11191122
self.emit_ins(X86Instruction::call_immediate(self.relative_to_anchor(ANCHOR_INTERNAL_FUNCTION_CALL_REG, 5)));
11201123
},
11211124
Value::Constant64(target_pc, user_provided) => {
@@ -1477,6 +1480,7 @@ impl<'a, C: ContextObject> JitCompiler<'a, C> {
14771480
// Handler for EbpfError::CallOutsideTextSegment
14781481
self.set_anchor(ANCHOR_CALL_OUTSIDE_TEXT_SEGMENT);
14791482
self.emit_set_exception_kind(EbpfError::CallOutsideTextSegment);
1483+
self.emit_ins(X86Instruction::load(OperandSize::S64, RSP, REGISTER_SCRATCH, X86IndirectAccess::OffsetIndexShift(-8, RSP, 0)));
14801484
self.emit_ins(X86Instruction::jump_immediate(self.relative_to_anchor(ANCHOR_THROW_EXCEPTION, 5)));
14811485

14821486
// Handler for EbpfError::DivideByZero
@@ -1556,43 +1560,35 @@ impl<'a, C: ContextObject> JitCompiler<'a, C> {
15561560
self.emit_ins(X86Instruction::return_near());
15571561

15581562
// Routine for emit_internal_call(Value::Register())
1559-
// Inputs: Guest current pc in REGISTER_SCRATCH, Guest target address in REGISTER_MAP[FRAME_PTR_REG]
1560-
// Outputs: Guest target pc in REGISTER_SCRATCH, Host target address in RIP
1563+
// Inputs: Guest current pc in X86IndirectAccess::OffsetIndexShift(-16, RSP, 0), Guest target address in REGISTER_SCRATCH
1564+
// Outputs: Guest current pc in X86IndirectAccess::OffsetIndexShift(-16, RSP, 0), Guest target pc in REGISTER_SCRATCH, Host target address in RIP
15611565
self.set_anchor(ANCHOR_INTERNAL_FUNCTION_CALL_REG);
15621566
self.emit_ins(X86Instruction::push(REGISTER_MAP[0], None));
1563-
// REGISTER_SCRATCH contains the current program counter, and we must store it for proper
1564-
// error handling. We can discard the value if callx succeeds, so we are not incrementing
1565-
// the stack pointer (RSP).
1566-
self.emit_ins(X86Instruction::store(OperandSize::S64, REGISTER_SCRATCH, RSP, X86IndirectAccess::OffsetIndexShift(-8, RSP, 0)));
1567-
self.emit_ins(X86Instruction::mov(OperandSize::S64, REGISTER_MAP[FRAME_PTR_REG], REGISTER_MAP[0]));
15681567
// Calculate offset relative to program_vm_addr
1569-
self.emit_ins(X86Instruction::load_immediate(OperandSize::S64, REGISTER_MAP[FRAME_PTR_REG], self.program_vm_addr as i64));
1570-
self.emit_ins(X86Instruction::alu(OperandSize::S64, 0x29, REGISTER_MAP[FRAME_PTR_REG], REGISTER_MAP[0], 0, None)); // guest_target_address -= self.program_vm_addr;
1568+
self.emit_ins(X86Instruction::load_immediate(OperandSize::S64, REGISTER_MAP[0], self.program_vm_addr as i64));
1569+
self.emit_ins(X86Instruction::alu(OperandSize::S64, 0x29, REGISTER_MAP[0], REGISTER_SCRATCH, 0, None)); // guest_target_address -= self.program_vm_addr;
15711570
// Force alignment of guest_target_address
1572-
self.emit_ins(X86Instruction::alu(OperandSize::S64, 0x81, 4, REGISTER_MAP[0], !(INSN_SIZE as i64 - 1), None)); // guest_target_address &= !(INSN_SIZE - 1);
1571+
self.emit_ins(X86Instruction::alu(OperandSize::S64, 0x81, 4, REGISTER_SCRATCH, !(INSN_SIZE as i64 - 1), None)); // guest_target_address &= !(INSN_SIZE - 1);
15731572
// Bound check
15741573
// if(guest_target_address >= number_of_instructions * INSN_SIZE) throw CALL_OUTSIDE_TEXT_SEGMENT;
15751574
let number_of_instructions = self.result.pc_section.len();
1576-
self.emit_ins(X86Instruction::cmp_immediate(OperandSize::S64, REGISTER_MAP[0], (number_of_instructions * INSN_SIZE) as i64, None)); // guest_target_address.cmp(number_of_instructions * INSN_SIZE)
1575+
self.emit_ins(X86Instruction::cmp_immediate(OperandSize::S64, REGISTER_SCRATCH, (number_of_instructions * INSN_SIZE) as i64, None)); // guest_target_address.cmp(number_of_instructions * INSN_SIZE)
15771576
self.emit_ins(X86Instruction::conditional_jump_immediate(0x83, self.relative_to_anchor(ANCHOR_CALL_OUTSIDE_TEXT_SEGMENT, 6)));
15781577
// First half of self.emit_profile_instruction_count(false, None);
1579-
self.emit_ins(X86Instruction::alu(OperandSize::S64, 0x29, REGISTER_SCRATCH, REGISTER_INSTRUCTION_METER, 0, None)); // instruction_meter -= guest_current_pc;
1578+
self.emit_ins(X86Instruction::alu(OperandSize::S64, 0x2b, REGISTER_INSTRUCTION_METER, RSP, 0, Some(X86IndirectAccess::OffsetIndexShift(-8, RSP, 0)))); // instruction_meter -= guest_current_pc;
15801579
self.emit_ins(X86Instruction::alu(OperandSize::S64, 0x81, 5, REGISTER_INSTRUCTION_METER, 1, None)); // instruction_meter -= 1;
1581-
// Calculate the target_pc (dst / INSN_SIZE) to update REGISTER_INSTRUCTION_METER
1582-
// and as target pc for potential ANCHOR_CALL_UNSUPPORTED_INSTRUCTION
1580+
// Load host target_address from self.result.pc_section
1581+
debug_assert_eq!(INSN_SIZE, 8); // Because the instruction size is also the slot size we do not need to shift the offset
1582+
self.emit_ins(X86Instruction::load_immediate(OperandSize::S64, REGISTER_MAP[0], self.result.pc_section.as_ptr() as i64)); // host_target_address = self.result.pc_section;
1583+
self.emit_ins(X86Instruction::alu(OperandSize::S64, 0x01, REGISTER_SCRATCH, REGISTER_MAP[0], 0, None)); // host_target_address += guest_target_address;
1584+
self.emit_ins(X86Instruction::load(OperandSize::S64, REGISTER_MAP[0], REGISTER_MAP[0], X86IndirectAccess::Offset(0))); // host_target_address = self.result.pc_section[host_target_address / 8];
1585+
// Calculate the guest_target_pc (dst / INSN_SIZE) to update REGISTER_INSTRUCTION_METER
1586+
// and as target_pc for potential ANCHOR_CALL_UNSUPPORTED_INSTRUCTION
15831587
let shift_amount = INSN_SIZE.trailing_zeros();
15841588
debug_assert_eq!(INSN_SIZE, 1 << shift_amount);
1585-
self.emit_ins(X86Instruction::mov(OperandSize::S64, REGISTER_MAP[0], REGISTER_SCRATCH)); // guest_target_pc = guest_target_address;
15861589
self.emit_ins(X86Instruction::alu(OperandSize::S64, 0xc1, 5, REGISTER_SCRATCH, shift_amount as i64, None)); // guest_target_pc /= INSN_SIZE;
15871590
// Second half of self.emit_profile_instruction_count(false, None);
15881591
self.emit_ins(X86Instruction::alu(OperandSize::S64, 0x01, REGISTER_SCRATCH, REGISTER_INSTRUCTION_METER, 0, None)); // instruction_meter += guest_target_pc;
1589-
// Load host target_address from self.result.pc_section
1590-
debug_assert_eq!(INSN_SIZE, 8); // Because the instruction size is also the slot size we do not need to shift the offset
1591-
self.emit_ins(X86Instruction::load_immediate(OperandSize::S64, REGISTER_MAP[FRAME_PTR_REG], self.result.pc_section.as_ptr() as i64));
1592-
self.emit_ins(X86Instruction::alu(OperandSize::S64, 0x01, REGISTER_MAP[FRAME_PTR_REG], REGISTER_MAP[0], 0, None)); // host_target_address = guest_target_address + self.result.pc_section;
1593-
self.emit_ins(X86Instruction::load(OperandSize::S64, REGISTER_MAP[0], REGISTER_MAP[0], X86IndirectAccess::Offset(0))); // host_target_address = self.result.pc_section[host_target_address / 8];
1594-
// Load the frame pointer again since we've clobbered REGISTER_MAP[FRAME_PTR_REG]
1595-
self.emit_ins(X86Instruction::load(OperandSize::S64, REGISTER_PTR_TO_VM, REGISTER_MAP[FRAME_PTR_REG], stack_pointer_access));
15961592
// Restore the clobbered REGISTER_MAP[0]
15971593
self.emit_ins(X86Instruction::xchg(OperandSize::S64, REGISTER_MAP[0], RSP, Some(X86IndirectAccess::OffsetIndexShift(0, RSP, 0)))); // Swap REGISTER_MAP[0] and host_target_address
15981594
self.emit_ins(X86Instruction::return_near()); // Tail call to host_target_address

0 commit comments

Comments
 (0)