feat(core): implement x86_64 dynamic relocation calculation engine
This commit is contained in:
parent
9a1224d9a8
commit
298884e194
3 changed files with 86 additions and 0 deletions
|
|
@ -2,4 +2,5 @@
|
|||
pub mod dynamic;
|
||||
pub mod elf;
|
||||
pub mod mmap;
|
||||
pub mod reloc;
|
||||
pub mod symbols;
|
||||
|
|
|
|||
65
crates/molotov-core/src/reloc.rs
Normal file
65
crates/molotov-core/src/reloc.rs
Normal 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(())
|
||||
}
|
||||
20
crates/molotov-core/tests/reloc_test.rs
Normal file
20
crates/molotov-core/tests/reloc_test.rs
Normal 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);
|
||||
}
|
||||
Reference in a new issue