You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
178 lines
4.7 KiB
Rust
178 lines
4.7 KiB
Rust
use std::iter::once;
|
|
|
|
use crate::common::{Relocatable, Section, SectionInfo, Symbol};
|
|
use crate::error::Error;
|
|
|
|
pub enum SegmentType {
|
|
Text,
|
|
Data,
|
|
Bss,
|
|
}
|
|
|
|
#[derive(Default)]
|
|
pub struct SegmentSections {
|
|
sections_info: Vec<SectionInfo>,
|
|
data_size: u64,
|
|
}
|
|
|
|
impl SegmentSections {
|
|
pub fn push(&mut self, si: SectionInfo) {
|
|
self.data_size += si.data_size;
|
|
self.sections_info.push(si);
|
|
}
|
|
|
|
pub fn iter(&self) -> impl Iterator<Item = &SectionInfo> {
|
|
self.sections_info.iter()
|
|
}
|
|
|
|
pub fn data_size(&self) -> u64 {
|
|
self.data_size
|
|
}
|
|
}
|
|
|
|
#[derive(Default)]
|
|
pub struct Loadable {
|
|
start_offset: Option<u64>,
|
|
|
|
text: SegmentSections,
|
|
rodata: SegmentSections,
|
|
data: SegmentSections,
|
|
bss: SegmentSections,
|
|
// symbol_map: HashMap<Rc<str>, Symbol>,
|
|
}
|
|
|
|
impl Loadable {
|
|
pub fn process_section(&mut self, section: Section) -> Result<(), Error> {
|
|
match section {
|
|
Section::Text(si) => self.text.push(si),
|
|
Section::Data(si, true) => self.rodata.push(si),
|
|
Section::Data(si, false) => self.data.push(si),
|
|
Section::Bss(si) => self.bss.push(si),
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn process_symbol<R>(&mut self, _symbol: Symbol, _objects: &[R]) -> Result<(), Error>
|
|
where
|
|
R: Relocatable,
|
|
{
|
|
Ok(())
|
|
// if symbol.binding == Binding::Local {
|
|
// return Ok(()); // local symbols are not stored
|
|
// }
|
|
|
|
// let key = Rc::from(symbol.name.as_str());
|
|
// let object_index = symbol.object_index;
|
|
|
|
// if let Some(prev) = self.symbol_map.insert(key, symbol) {
|
|
// let prev_trace = Trace {
|
|
// origin: objects[prev.object_index].origin().into(),
|
|
// ..Default::default()
|
|
// };
|
|
// let symbol_trace = Trace {
|
|
// origin: objects[object_index].origin().into(),
|
|
// ..Default::default()
|
|
// };
|
|
// let link_error = LinkError {
|
|
// message: format!("Duplicate global symbol found: {}", prev.name),
|
|
// code: LE_GLOBAL_SYMBOL_DUPLICATE,
|
|
// traces: vec![prev_trace, symbol_trace],
|
|
// };
|
|
// Err(Error::LinkingError(link_error))
|
|
// } else {
|
|
// Ok(())
|
|
// }
|
|
}
|
|
|
|
pub fn segment_sections(&self) -> impl Iterator<Item = &SegmentSections> {
|
|
let text = once(&self.text);
|
|
let rodata = once(&self.rodata);
|
|
let data = once(&self.data);
|
|
let bss = once(&self.bss);
|
|
|
|
text.chain(rodata).chain(data).chain(bss)
|
|
}
|
|
|
|
pub fn program_bytes<'l, R: Relocatable>(
|
|
&'l self,
|
|
objects: &'l [R],
|
|
) -> impl Iterator<Item = Result<&'l [u8], Error>> {
|
|
let text_iter = self.text.iter();
|
|
let rodata_iter = self.rodata.iter();
|
|
|
|
let data1 = text_iter.filter_map(move |si| match si.file_size {
|
|
0 => None,
|
|
_ => Some(objects[si.object_index].bytes(si.offset, si.file_size)),
|
|
});
|
|
let data2 = rodata_iter.filter_map(move |si| match si.data_size {
|
|
0 => None,
|
|
_ => Some(objects[si.object_index].bytes(si.offset, si.file_size)),
|
|
});
|
|
|
|
data1.chain(data2)
|
|
}
|
|
|
|
pub fn data_bytes<'l, R: Relocatable>(
|
|
&'l self,
|
|
objects: &'l [R],
|
|
) -> impl Iterator<Item = Result<&'l [u8], Error>> {
|
|
let iter = self.data.iter().filter_map(move |si| match si.file_size {
|
|
0 => None,
|
|
_ => Some(objects[si.object_index].bytes(si.offset, si.file_size)),
|
|
});
|
|
|
|
iter
|
|
}
|
|
|
|
// .text + .rodata
|
|
pub fn program_size(&self) -> u64 {
|
|
let text_iter = self.text.iter();
|
|
let rodata_iter = self.rodata.iter();
|
|
|
|
let mut result = 0u64;
|
|
for section in text_iter.chain(rodata_iter) {
|
|
result += section.data_size
|
|
}
|
|
|
|
result
|
|
}
|
|
|
|
// data
|
|
pub fn data_size(&self) -> u64 {
|
|
let mut result = 0u64;
|
|
for section in self.data.iter() {
|
|
result += section.data_size
|
|
}
|
|
|
|
result
|
|
}
|
|
|
|
// bss
|
|
pub fn bss_size(&self) -> u64 {
|
|
let mut result = 0u64;
|
|
for section in self.bss.iter() {
|
|
result += section.data_size
|
|
}
|
|
|
|
result
|
|
}
|
|
|
|
pub fn set_start_offset(&mut self, offset: u64) {
|
|
self.start_offset = Some(offset);
|
|
}
|
|
|
|
pub fn start_offset(&self) -> Result<u64, Error> {
|
|
use crate::error::LinkError;
|
|
|
|
self.start_offset.ok_or_else(|| {
|
|
let link_error = LinkError {
|
|
message: "Program entrypoint not found".into(),
|
|
..Default::default()
|
|
};
|
|
|
|
Error::LinkingError(link_error)
|
|
})
|
|
}
|
|
}
|