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::Risc => 8,
60        };
61        match self {
62            Section::Text(text) => {
63                let mut data = text.data.clone();
64                for relocation in text.relocations.iter() {
65                    let symbol = placement.find_symbol(relocation.symbol.as_str());
66                    let symbol = match symbol {
67                        None => return Err(LinkerError::SymbolNotFound(relocation.symbol.clone())),
68                        Some(symbol) => symbol,
69                    };
70                    let offset = if relocation.relative {
71                        symbol - relocation.address
72                    } else {
73                        symbol.0 as i64
74                    } / (text_byte_width as i64);
75                    // Check bounds - +-2^16
76                    if offset > 2_i64.pow(16) as i64 || offset < -(2_i64.pow(16) as i64) {
77                        return Err(LinkerError::RelocationOutOfRange(relocation.symbol.clone()));
78                    }
79                    data.write(
80                        relocation.address,
81                        data.index(relocation.address).wrapping_add(offset as u16),
82                    );
83                }
84                Ok(Segment::new(
85                    offset as u64,
86                    ((data.len() + text_byte_width - 1) / text_byte_width) as u64,
87                    data.len(),
88                    SegmentFlags {
89                        writable: false,
90                        executable: true,
91                        readable: true,
92                        special: false,
93                    },
94                    data,
95                    text.symbols.clone(),
96                ))
97            }
98        }
99    }
100}