monistode_binutils/object_file/sections/
common.rs

1use super::header::{SectionHeader, TextSectionHeader};
2use super::text::TextSection;
3use crate::address::AddressIndexable;
4use crate::executable::segments::flags::SegmentFlags;
5use crate::executable::segments::Segment;
6use crate::object_file::placed::{LinkerError, Placement};
7use crate::object_file::relocations::Relocation;
8use crate::serializable::{Architecture, SerializationError};
9use crate::symbols::Symbol;
10
11#[derive(Debug, Clone)]
12pub enum Section {
13    Text(TextSection),
14}
15
16impl Section {
17    pub fn serialize(&self) -> (SectionHeader, Vec<u8>) {
18        match self {
19            Section::Text(text) => {
20                let bytes = text.serialize();
21                let section_header = SectionHeader::Text(TextSectionHeader {
22                    bit_length: text.data.len(),
23                });
24                (section_header, bytes)
25            }
26        }
27    }
28
29    pub fn deserialize(
30        header: &SectionHeader,
31        data: &[u8],
32        symbols: Vec<Symbol>,
33        relocations: Vec<Relocation>,
34    ) -> Result<(usize, Self), SerializationError> {
35        match header {
36            SectionHeader::Text(header) => {
37                let (size, section) = TextSection::deserialize(header, data, symbols, relocations)?;
38                Ok((size, Section::Text(section)))
39            }
40            _ => Err(SerializationError::InvalidSectionType(0)),
41        }
42    }
43
44    pub fn symbols(&self) -> Vec<Symbol> {
45        match self {
46            Section::Text(text) => text.symbols.clone(),
47        }
48    }
49
50    pub fn relocations(&self) -> Vec<Relocation> {
51        match self {
52            Section::Text(text) => text.relocations.clone(),
53        }
54    }
55
56    pub fn to_segment(&self, placement: &Placement, offset: usize) -> Result<Segment, LinkerError> {
57        let text_byte_width: usize = match placement.architecture() {
58            Architecture::Stack => 6,
59            Architecture::Accumulator => 8,
60            Architecture::Risc => 8,
61        };
62        match self {
63            Section::Text(text) => {
64                let mut data = text.data.clone();
65                for relocation in text.relocations.iter() {
66                    let symbol = placement.find_symbol(relocation.symbol.as_str());
67                    let symbol = match symbol {
68                        None => return Err(LinkerError::SymbolNotFound(relocation.symbol.clone())),
69                        Some(symbol) => symbol,
70                    };
71                    let offset = if relocation.relative {
72                        symbol - relocation.address
73                    } else {
74                        symbol.0 as i64
75                    } / (text_byte_width as i64);
76                    // Check bounds - +-2^16
77                    if offset > 2_i64.pow(16) as i64 || offset < -(2_i64.pow(16) as i64) {
78                        return Err(LinkerError::RelocationOutOfRange(relocation.symbol.clone()));
79                    }
80                    data.write(
81                        relocation.address,
82                        data.index(relocation.address).wrapping_add(offset as u16),
83                    );
84                }
85                Ok(Segment::new(
86                    offset as u64,
87                    ((data.len() + text_byte_width - 1) / text_byte_width) as u64,
88                    data.len(),
89                    SegmentFlags {
90                        writable: false,
91                        executable: true,
92                        readable: true,
93                        special: false,
94                    },
95                    data,
96                    text.symbols.clone(),
97                ))
98            }
99        }
100    }
101}