From 298884e1941d30ace87b6b21e03ada06eb001250 Mon Sep 17 00:00:00 2001 From: oiupoyt Date: Tue, 29 Sep 2026 17:05:34 +0530 Subject: [PATCH] feat(core): implement x86_64 dynamic relocation calculation engine --- crates/molotov-core/src/lib.rs | 1 + crates/molotov-core/src/reloc.rs | 65 +++++++++++++++++++++++++ crates/molotov-core/tests/reloc_test.rs | 20 ++++++++ 3 files changed, 86 insertions(+) create mode 100644 crates/molotov-core/src/reloc.rs create mode 100644 crates/molotov-core/tests/reloc_test.rs diff --git a/crates/molotov-core/src/lib.rs b/crates/molotov-core/src/lib.rs index 3c8563b..efd42d7 100644 --- a/crates/molotov-core/src/lib.rs +++ b/crates/molotov-core/src/lib.rs @@ -2,4 +2,5 @@ pub mod dynamic; pub mod elf; pub mod mmap; +pub mod reloc; pub mod symbols; diff --git a/crates/molotov-core/src/reloc.rs b/crates/molotov-core/src/reloc.rs new file mode 100644 index 0000000..ca1908f --- /dev/null +++ b/crates/molotov-core/src/reloc.rs @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +pub const R_X86_64_64: u32 = 1; +pub const R_X86_64_GLOB_DAT: u32 = 6; +pub const R_X86_64_JUMP_SLOT: u32 = 7; +pub const R_X86_64_RELATIVE: u32 = 8; + +#[derive(Debug, Clone)] +pub struct RelocationEntry { + pub offset: u64, + pub r_type: u32, + pub symbol_index: u32, + pub addend: i64, +} + +impl RelocationEntry { + pub fn parse_rela(bytes: &[u8]) -> Option { + if bytes.len() < 24 { + return None; + } + let offset = u64::from_le_bytes(bytes[0..8].try_into().ok()?); + let info = u64::from_le_bytes(bytes[8..16].try_into().ok()?); + let addend = i64::from_le_bytes(bytes[16..24].try_into().ok()?); + + let r_type = (info & 0xffff_ffff) as u32; + let symbol_index = (info >> 32) as u32; + + Some(Self { + offset, + r_type, + symbol_index, + addend, + }) + } +} + +pub fn apply_relative_relocation( + memory: &mut [u8], + base_slide: u64, + reloc: &RelocationEntry, +) -> Result<(), String> { + let target_offset = reloc.offset as usize; + if target_offset + 8 > memory.len() { + return Err(format!("Relocation offset 0x{:x} out of bounds", target_offset)); + } + + let target_val = (base_slide as i128 + reloc.addend as i128) as u64; + memory[target_offset..target_offset + 8].copy_from_slice(&target_val.to_le_bytes()); + Ok(()) +} + +pub fn apply_symbol_relocation( + memory: &mut [u8], + symbol_address: u64, + reloc: &RelocationEntry, +) -> Result<(), String> { + let target_offset = reloc.offset as usize; + if target_offset + 8 > memory.len() { + return Err(format!("Symbol relocation offset 0x{:x} out of bounds", target_offset)); + } + + let target_val = (symbol_address as i128 + reloc.addend as i128) as u64; + memory[target_offset..target_offset + 8].copy_from_slice(&target_val.to_le_bytes()); + Ok(()) +} diff --git a/crates/molotov-core/tests/reloc_test.rs b/crates/molotov-core/tests/reloc_test.rs new file mode 100644 index 0000000..236b490 --- /dev/null +++ b/crates/molotov-core/tests/reloc_test.rs @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +use molotov_core::reloc::{apply_relative_relocation, RelocationEntry, R_X86_64_RELATIVE}; + +#[test] +fn test_relative_relocation_adds_slide_and_addend() { + let mut memory = vec![0u8; 64]; + let base_slide: u64 = 0x7fff_0000_0000; + let addend: i64 = 0x1000; + let reloc = RelocationEntry { + offset: 8, + r_type: R_X86_64_RELATIVE, + symbol_index: 0, + addend, + }; + + apply_relative_relocation(&mut memory, base_slide, &reloc).expect("Relocation should apply cleanly"); + + let resolved = u64::from_le_bytes(memory[8..16].try_into().unwrap()); + assert_eq!(resolved, 0x7fff_0000_1000); +}