feat(core): implement x86_64 dynamic relocation calculation engine

This commit is contained in:
katR 2026-09-29 17:05:34 +05:30
parent 9a1224d9a8
commit 298884e194
3 changed files with 86 additions and 0 deletions

View file

@ -2,4 +2,5 @@
pub mod dynamic;
pub mod elf;
pub mod mmap;
pub mod reloc;
pub mod symbols;

View file

@ -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<Self> {
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(())
}

View file

@ -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);
}