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::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 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}