48 lines
1.6 KiB
Rust
48 lines
1.6 KiB
Rust
//! Simple flat-bytecode linker
|
||
|
||
use {
|
||
crate::{
|
||
object::{RelocKey, RelocType, Section},
|
||
SharedObject,
|
||
},
|
||
std::io::Write,
|
||
};
|
||
|
||
pub fn link(object: SharedObject, out: &mut impl Write) -> std::io::Result<()> {
|
||
let obj = &mut *object.borrow_mut();
|
||
|
||
// Walk relocation table entries
|
||
for (&loc, entry) in &obj.relocs {
|
||
let value = match &entry.key {
|
||
// Symbol – direct reference
|
||
RelocKey::Symbol(sym) => obj.symbols[*sym],
|
||
|
||
// Label – indirect label reference
|
||
RelocKey::Label(label) => obj.symbols[obj.labels[label]],
|
||
}
|
||
.ok_or_else(|| std::io::Error::other("Invalid symbol"))?;
|
||
|
||
let offset = match value.location {
|
||
// Text section is on the beginning
|
||
Section::Text => value.offset,
|
||
|
||
// Data section follows text section immediately
|
||
Section::Data => value.offset + obj.sections.text.len(),
|
||
};
|
||
|
||
// Insert address or calulate relative offset
|
||
match entry.ty {
|
||
RelocType::Rel32 => obj.sections.text[loc..loc + 4]
|
||
.copy_from_slice(&((offset as isize - loc as isize) as i32).to_le_bytes()),
|
||
RelocType::Rel16 => obj.sections.text[loc..loc + 2]
|
||
.copy_from_slice(&((offset as isize - loc as isize) as i16).to_le_bytes()),
|
||
RelocType::Abs64 => obj.sections.text[loc..loc + 8]
|
||
.copy_from_slice(&(offset as isize - loc as isize).to_le_bytes()),
|
||
}
|
||
}
|
||
|
||
// Write to output
|
||
out.write_all(&obj.sections.text)?;
|
||
out.write_all(&obj.sections.data)
|
||
}
|