monistode_binutils/object_file/placed/
mod.rs

1use crate::{executable::segments::Segment, Address, Architecture};
2
3use super::Section;
4
5#[derive(Debug)]
6pub enum LinkerError {
7    SymbolNotFound(String),
8    RelocationOutOfRange(String),
9}
10
11pub struct PlacedSection {
12    section: Section,
13    offset: usize, // in bytes
14}
15
16#[derive(Debug, Clone, Eq, PartialEq)]
17pub enum SectionType {
18    TextSpace,
19    DataSpace,
20    Unified,
21}
22
23impl PlacedSection {
24    pub fn new(section: Section) -> Self {
25        PlacedSection { section, offset: 0 }
26    }
27
28    pub fn section(&self) -> &Section {
29        &self.section
30    }
31
32    pub fn section_type(&self) -> SectionType {
33        SectionType::Unified // TODO
34    }
35
36    pub fn offset(&self) -> usize {
37        self.offset
38    }
39
40    pub fn size(&self, architecture: Architecture) -> usize {
41        let text_byte_width = match architecture {
42            Architecture::Stack => 6,
43            Architecture::Accumulator => 8,
44            Architecture::Risc => 8,
45        };
46        match &self.section {
47            Section::Text(text) => (text.data.len() + text_byte_width - 1) / text_byte_width,
48        }
49    }
50
51    pub fn find_symbol(&self, name: &str) -> Option<Address> {
52        for symbol in self.section.symbols().iter() {
53            if symbol.name == name {
54                return Some(symbol.address + self.offset);
55            }
56        }
57        return None;
58    }
59
60    pub fn to(&mut self, offset: usize) {
61        self.offset = offset;
62    }
63}
64
65pub struct Placement {
66    sections: Vec<PlacedSection>,
67    architecture: Architecture,
68}
69
70impl Placement {
71    pub fn new(sections: Vec<PlacedSection>, architecture: Architecture) -> Self {
72        Placement {
73            sections,
74            architecture,
75        }
76    }
77
78    pub fn architecture(&self) -> Architecture {
79        self.architecture
80    }
81
82    pub fn find_symbol(&self, name: &str) -> Option<Address> {
83        for section in self.sections.iter() {
84            if let Some(address) = section.find_symbol(name) {
85                return Some(address);
86            }
87        }
88        return None;
89    }
90
91    pub fn place(&mut self) {
92        // We need to make sure no segments intersect
93        for address_space in [
94            SectionType::TextSpace,
95            SectionType::DataSpace,
96            SectionType::Unified,
97        ]
98        .iter()
99        {
100            let mut last_end = 0;
101            for section in self.sections.iter_mut() {
102                if section.section_type() != *address_space {
103                    continue;
104                }
105                section.to(last_end);
106                last_end = section.offset() + section.size(self.architecture);
107            }
108        }
109    }
110
111    pub fn as_segments(&self) -> Result<Vec<Segment>, LinkerError> {
112        self.sections
113            .iter()
114            .map(|section| section.section().to_segment(self, section.offset()))
115            .collect()
116    }
117}