holey-bytes/hbasm/src/linker.rs

48 lines
1.6 KiB
Rust
Raw Normal View History

2024-02-22 16:57:29 -06:00
//! Simple flat-bytecode linker
2023-10-27 20:29:02 -05:00
use {
crate::{
object::{RelocKey, RelocType, Section},
SharedObject,
},
std::io::Write,
};
2023-10-27 20:29:02 -05:00
pub fn link(object: SharedObject, out: &mut impl Write) -> std::io::Result<()> {
let obj = &mut *object.borrow_mut();
2024-02-22 16:57:29 -06:00
// Walk relocation table entries
2023-10-27 20:29:02 -05:00
for (&loc, entry) in &obj.relocs {
let value = match &entry.key {
2024-02-22 16:57:29 -06:00
// Symbol direct reference
2023-10-27 20:29:02 -05:00
RelocKey::Symbol(sym) => obj.symbols[*sym],
2024-02-22 16:57:29 -06:00
// Label indirect label reference
2023-10-27 20:29:02 -05:00
RelocKey::Label(label) => obj.symbols[obj.labels[label]],
}
.ok_or_else(|| std::io::Error::other("Invalid symbol"))?;
let offset = match value.location {
2024-02-22 16:57:29 -06:00
// Text section is on the beginning
2023-10-27 20:29:02 -05:00
Section::Text => value.offset,
2024-02-22 16:57:29 -06:00
// Data section follows text section immediately
2023-10-27 20:29:02 -05:00
Section::Data => value.offset + obj.sections.text.len(),
};
2024-02-22 16:57:29 -06:00
// Insert address or calulate relative offset
2023-10-27 20:29:02 -05:00
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()),
}
}
2024-02-22 16:57:29 -06:00
// Write to output
2023-10-27 20:29:02 -05:00
out.write_all(&obj.sections.text)?;
out.write_all(&obj.sections.data)
}