From a8c8834a3cc4367dba5bb16c9fe7addbbfa18589 Mon Sep 17 00:00:00 2001 From: Folkert Date: Sat, 16 Sep 2023 15:57:03 +0200 Subject: [PATCH] actually understand this jmp address bug --- .../compiler/gen_dev/src/generic64/aarch64.rs | 26 +++---------------- crates/compiler/gen_dev/src/generic64/mod.rs | 14 +++++++++- .../compiler/gen_dev/src/generic64/x86_64.rs | 23 +++------------- 3 files changed, 20 insertions(+), 43 deletions(-) diff --git a/crates/compiler/gen_dev/src/generic64/aarch64.rs b/crates/compiler/gen_dev/src/generic64/aarch64.rs index 010a0c9d18..7d7c955f4f 100644 --- a/crates/compiler/gen_dev/src/generic64/aarch64.rs +++ b/crates/compiler/gen_dev/src/generic64/aarch64.rs @@ -1116,27 +1116,8 @@ impl Assembler for AArch64Assembler { todo!("jump offsets over 27 bits for AArch64: {:#x}", offset); } - buf.len() - } - - /// Updates a jump instruction to a new offset and returns the number of bytes written. - fn update_jmp_imm32_offset( - buf: &mut Vec<'_, u8>, - jmp_location: u64, - base_offset: u64, - target_offset: u64, - ) { - let old_buf_len = buf.len(); - - // write the jmp at the back of buf - let jmp_offset = target_offset as i32 - base_offset as i32 + 4; - Self::jmp_imm32(buf, jmp_offset); - - // move the new jmp instruction into position - buf.copy_within(old_buf_len.., jmp_location as usize); - - // wipe the jmp we created at the end - buf.truncate(old_buf_len) + // on aarch64, jumps are calculated from the start of the jmp instruction + buf.len() - 4 } #[inline(always)] @@ -1172,7 +1153,8 @@ impl Assembler for AArch64Assembler { todo!("jump offsets over 20 bits for AArch64: {:#x}", offset); } - buf.len() + // on aarch64, jumps are calculated from the start of the jmp instruction + buf.len() - 4 } #[inline(always)] diff --git a/crates/compiler/gen_dev/src/generic64/mod.rs b/crates/compiler/gen_dev/src/generic64/mod.rs index 026fa7f5e1..131a3c6704 100644 --- a/crates/compiler/gen_dev/src/generic64/mod.rs +++ b/crates/compiler/gen_dev/src/generic64/mod.rs @@ -263,7 +263,19 @@ pub trait Assembler: Sized + Copy { jmp_location: u64, base_offset: u64, target_offset: u64, - ); + ) { + let old_buf_len = buf.len(); + + // write the jmp at the back of buf + let jmp_offset = target_offset as i32 - base_offset as i32; + Self::jmp_imm32(buf, jmp_offset); + + // move the new jmp instruction into position + buf.copy_within(old_buf_len.., jmp_location as usize); + + // wipe the jmp we created at the end + buf.truncate(old_buf_len) + } fn tail_call(buf: &mut Vec<'_, u8>) -> u64; diff --git a/crates/compiler/gen_dev/src/generic64/x86_64.rs b/crates/compiler/gen_dev/src/generic64/x86_64.rs index dcfb26c904..793849241a 100644 --- a/crates/compiler/gen_dev/src/generic64/x86_64.rs +++ b/crates/compiler/gen_dev/src/generic64/x86_64.rs @@ -2111,29 +2111,11 @@ impl Assembler for X86_64Assembler { #[inline(always)] fn jmp_imm32(buf: &mut Vec<'_, u8>, offset: i32) -> usize { jmp_imm32(buf, offset); + + // on x86_64, jumps are calculated from the end of the jmp instruction buf.len() } - /// Updates a jump instruction to a new offset and returns the number of bytes written. - fn update_jmp_imm32_offset( - buf: &mut Vec<'_, u8>, - jmp_location: u64, - base_offset: u64, - target_offset: u64, - ) { - let old_buf_len = buf.len(); - - // write the jmp at the back of buf - let jmp_offset = target_offset as i32 - base_offset as i32; - Self::jmp_imm32(buf, jmp_offset); - - // move the new jmp instruction into position - buf.copy_within(old_buf_len.., jmp_location as usize); - - // wipe the jmp we created at the end - buf.truncate(old_buf_len) - } - #[inline(always)] fn tail_call(buf: &mut Vec<'_, u8>) -> u64 { Self::jmp_imm32(buf, 0); @@ -2164,6 +2146,7 @@ impl Assembler for X86_64Assembler { jne_imm32(buf, offset); + // on x86_64, jumps are calculated from the end of the jmp instruction buf.len() }