monistode_binutils/object_file/placed/
mod.rs1use 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, }
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 }
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 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}