monistode_binutils/object_file/sections/
common.rs1use 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 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}