feat(core): implement end-to-end BionicLinker library loader

This commit is contained in:
katR 2026-09-29 17:08:08 +05:30
parent 4702aaa37c
commit 0ffddd2f3d
3 changed files with 91 additions and 0 deletions

View file

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pub mod dynamic;
pub mod elf;
pub mod linker;
pub mod mmap;
pub mod reloc;
pub mod symbols;

View file

@ -0,0 +1,81 @@
// SPDX-License-Identifier: GPL-3.0-or-later
use crate::elf::ElfBinary;
use crate::mmap::MappedImage;
use crate::symbols::SymbolTriage;
pub struct LoadedLibrary {
pub mapping: MappedImage,
pub base_addr: u64,
}
pub struct BionicLinker {
triage: SymbolTriage,
}
impl Default for BionicLinker {
fn default() -> Self {
Self::new()
}
}
impl BionicLinker {
pub fn new() -> Self {
Self {
triage: SymbolTriage::new(),
}
}
pub fn triage(&self) -> &SymbolTriage {
&self.triage
}
pub fn triage_mut(&mut self) -> &mut SymbolTriage {
&mut self.triage
}
pub fn load_from_bytes(&self, bytes: &[u8]) -> Result<LoadedLibrary, String> {
let elf = ElfBinary::parse(bytes).map_err(|e| e.to_string())?;
// Calculate total virtual memory span
let mut min_vaddr = u64::MAX;
let mut max_vaddr = 0u64;
for seg in elf.load_segments() {
if seg.p_vaddr < min_vaddr {
min_vaddr = seg.p_vaddr;
}
let seg_end = seg.p_vaddr + seg.p_memsz;
if seg_end > max_vaddr {
max_vaddr = seg_end;
}
}
if min_vaddr > max_vaddr {
return Err("No PT_LOAD segments found in ELF binary".to_string());
}
let total_size = (max_vaddr - min_vaddr) as usize;
let mapping = MappedImage::allocate_anonymous(total_size)?;
let base_addr = mapping.base_addr() as u64;
// Copy PT_LOAD segments into virtual memory
for seg in elf.load_segments() {
let seg_dest_offset = (seg.p_vaddr - min_vaddr) as usize;
let file_start = seg.p_offset as usize;
let file_end = file_start + seg.p_filesz as usize;
if file_end <= bytes.len() {
let slice = &bytes[file_start..file_end];
unsafe {
let dest_ptr = mapping.base_addr().add(seg_dest_offset);
std::ptr::copy_nonoverlapping(slice.as_ptr(), dest_ptr, slice.len());
}
}
}
Ok(LoadedLibrary {
mapping,
base_addr,
})
}
}

View file

@ -0,0 +1,9 @@
// SPDX-License-Identifier: GPL-3.0-or-later
use molotov_core::linker::BionicLinker;
#[test]
fn test_linker_rejects_empty_data() {
let linker = BionicLinker::new();
let res = linker.load_from_bytes(&[]);
assert!(res.is_err());
}