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