monistode_binutils/executable/
mod.rs

1pub use header::ExecutableHeader;
2pub use segments::{Segment, SegmentHeader};
3
4use crate::{Architecture, Serializable, SerializationError, SymbolTable};
5
6pub mod header;
7pub mod segments;
8
9#[derive(Debug, Clone)]
10pub struct Executable {
11    architecture: Architecture,
12    entry_point: u64,
13    segments: Vec<Segment>,
14}
15
16impl Serializable for Executable {
17    fn serialize(&self) -> Vec<u8> {
18        let mut data = Vec::new();
19
20        // Optionally create symbol table from segment data - using the same section based table
21        // because why not
22        let mut symbol_table = SymbolTable::new();
23
24        for (segment_id, segment) in self.segments.iter().enumerate() {
25            for symbol in segment.symbols() {
26                symbol_table.add_symbol(segment_id as u32, symbol);
27            }
28        }
29
30        // Serialize header with all segments (including symbol table)
31        let header = ExecutableHeader {
32            architecture: self.architecture,
33            segment_count: self.segments.len() as u64 + 1, // +1 for symbol table
34            entry_point: self.entry_point,
35        };
36        data.extend(header.serialize());
37
38        // Create and serialize all segment headers and data
39        let mut segment_data = Vec::new();
40        let mut headers = Vec::new();
41
42        // Add regular segment headers first
43        for segment in &self.segments {
44            let (header, bytes) = segment.serialize();
45            headers.push(header);
46            segment_data.extend(bytes);
47        }
48
49        // Add symbol table headers last
50        let (symbol_header, symbol_data) = symbol_table.serialize_as_segment();
51        headers.push(symbol_header);
52        segment_data.extend(symbol_data);
53
54        // Add all headers followed by all segment data
55        for header in headers {
56            data.extend(header.serialize());
57        }
58        data.extend(segment_data);
59
60        data
61    }
62
63    fn deserialize(data: &[u8]) -> Result<(usize, Self), SerializationError> {
64        if data.len() < 9 {
65            return Err(SerializationError::DataTooShort);
66        }
67
68        // Parse header
69        let (header_size, header) = ExecutableHeader::deserialize(data)?;
70        let mut offset = header_size;
71
72        // Read all segment headers
73        let mut headers = Vec::new();
74        for _ in 0..header.segment_count {
75            if data.len() < offset + 16 {
76                // Minimum segment header size
77                return Err(SerializationError::DataTooShort);
78            }
79            let (size, segment_header) = SegmentHeader::deserialize(&data[offset..])?;
80            headers.push(segment_header);
81            offset += size;
82        }
83
84        // Last segment must be symbol table - TODO optional
85        let segment_count = headers.len();
86        if segment_count < 1 {
87            return Err(SerializationError::InvalidData);
88        }
89        if !headers[segment_count - 1].flags.special
90            || !headers[segment_count - 1].address_space_start == 0
91        {
92            return Err(SerializationError::InvalidData);
93        }
94
95        // Ensure no other symbol table segments exist
96        if headers[..segment_count - 1]
97            .iter()
98            .any(|h| h.flags.special && h.address_space_start == 0)
99        {
100            return Err(SerializationError::InvalidData);
101        }
102
103        // Calculate offsets to symbol and relocation tables
104        let mut segment_data_offset = offset;
105        for header in &headers[..segment_count - 1] {
106            segment_data_offset += header.segment_size();
107        }
108
109        // Load symbol table first
110        let symbol_offset = segment_data_offset;
111        let (_, symbol_table) =
112            SymbolTable::deserialize_segment(&headers[segment_count - 1], &data[symbol_offset..])?;
113
114        // Process regular segments
115        let mut segments = Vec::new();
116        let mut current_offset = offset;
117
118        for (idx, segment_header) in headers[..segment_count - 1].iter().enumerate() {
119            let symbols = symbol_table.get_symbols(idx as u32);
120            let (size, segment) =
121                Segment::deserialize(segment_header, &data[current_offset..], symbols)?;
122            segments.push(segment);
123            current_offset += size;
124        }
125
126        Ok((
127            symbol_offset + headers[segment_count - 1].segment_size(), // TODO sure?
128            Executable {
129                architecture: header.architecture,
130                entry_point: header.entry_point,
131                segments,
132            },
133        ))
134    }
135}
136
137impl Executable {
138    pub fn new(architecture: Architecture, segments: Vec<Segment>) -> Self {
139        Executable {
140            architecture,
141            segments,
142            entry_point: 0,
143        }
144    }
145
146    pub fn segments(&self) -> &[Segment] {
147        &self.segments
148    }
149
150    pub fn segments_mut(&mut self) -> &mut Vec<Segment> {
151        &mut self.segments
152    }
153
154    pub fn architecture(&self) -> Architecture {
155        self.architecture
156    }
157
158    pub fn entry_point(&self) -> u64 {
159        self.entry_point
160    }
161}