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::Risc => 8,
44        };
45        match &self.section {
46            Section::Text(text) => (text.data.len() + text_byte_width - 1) / text_byte_width,
47        }
48    }
49
50    pub fn find_symbol(&self, name: &str) -> Option<Address> {
51        for symbol in self.section.symbols().iter() {
52            if symbol.name == name {
53                return Some(symbol.address + self.offset);
54            }
55        }
56        return None;
57    }
58
59    pub fn to(&mut self, offset: usize) {
60        self.offset = offset;
61    }
62}
63
64pub struct Placement {
65    sections: Vec<PlacedSection>,
66    architecture: Architecture,
67}
68
69impl Placement {
70    pub fn new(sections: Vec<PlacedSection>, architecture: Architecture) -> Self {
71        Placement {
72            sections,
73            architecture,
74        }
75    }
76
77    pub fn architecture(&self) -> Architecture {
78        self.architecture
79    }
80
81    pub fn find_symbol(&self, name: &str) -> Option<Address> {
82        for section in self.sections.iter() {
83            if let Some(address) = section.find_symbol(name) {
84                return Some(address);
85            }
86        }
87        return None;
88    }
89
90    pub fn place(&mut self) {
91        // We need to make sure no segments intersect
92        for address_space in [
93            SectionType::TextSpace,
94            SectionType::DataSpace,
95            SectionType::Unified,
96        ]
97        .iter()
98        {
99            let mut last_end = 0;
100            for section in self.sections.iter_mut() {
101                if section.section_type() != *address_space {
102                    continue;
103                }
104                section.to(last_end);
105                last_end = section.offset() + section.size(self.architecture);
106            }
107        }
108    }
109
110    pub fn as_segments(&self) -> Result<Vec<Segment>, LinkerError> {
111        self.sections
112            .iter()
113            .map(|section| section.section().to_segment(self, section.offset()))
114            .collect()
115    }
116}