monistode_binutils/object_file/
mod.rs

1pub mod header;
2pub mod placed;
3pub mod relocations;
4pub mod sections;
5
6pub use header::ObjectHeader;
7pub use relocations::{Relocation, RelocationTable};
8pub use sections::*;
9
10use crate::{Architecture, Serializable, SerializationError, SymbolTable};
11
12#[derive(Debug, Clone)]
13pub struct ObjectFile {
14    architecture: Architecture,
15    sections: Vec<Section>,
16}
17
18impl Serializable for ObjectFile {
19    fn serialize(&self) -> Vec<u8> {
20        let mut data = Vec::new();
21
22        // Create symbol and relocation tables from section data
23        let mut symbol_table = SymbolTable::new();
24        let mut relocation_table = RelocationTable::new();
25
26        for (section_id, section) in self.sections.iter().enumerate() {
27            for symbol in section.symbols() {
28                symbol_table.add_symbol(section_id as u32, symbol);
29            }
30            for relocation in section.relocations() {
31                relocation_table.add_relocation(section_id as u32, relocation);
32            }
33        }
34
35        // Serialize header with all sections (including symbol and relocation tables)
36        let header = ObjectHeader {
37            architecture: self.architecture,
38            section_count: self.sections.len() as u64 + 2, // +2 for symbol and relocation tables
39        };
40        data.extend(header.serialize());
41
42        // Create and serialize all section headers and data
43        let mut section_data = Vec::new();
44        let mut headers = Vec::new();
45
46        // Add regular section headers first
47        for section in &self.sections {
48            let (header, bytes) = section.serialize();
49            headers.push(header);
50            section_data.extend(bytes);
51        }
52
53        // Add symbol and relocation table headers last
54        let (symbol_header, symbol_data) = symbol_table.serialize_as_section();
55        let (relocation_header, relocation_data) = relocation_table.serialize();
56        headers.push(symbol_header);
57        headers.push(relocation_header);
58        section_data.extend(symbol_data);
59        section_data.extend(relocation_data);
60
61        // Add all headers followed by all section data
62        for header in headers {
63            data.extend(header.serialize());
64        }
65        data.extend(section_data);
66
67        data
68    }
69
70    fn deserialize(data: &[u8]) -> Result<(usize, Self), SerializationError> {
71        if data.len() < 9 {
72            return Err(SerializationError::DataTooShort);
73        }
74
75        // Parse header
76        let (header_size, header) = ObjectHeader::deserialize(data)?;
77        let mut offset = header_size;
78
79        // Read all section headers
80        let mut headers = Vec::new();
81        for _ in 0..header.section_count {
82            if data.len() < offset + 16 {
83                // Minimum section header size
84                return Err(SerializationError::DataTooShort);
85            }
86            let (size, section_header) = SectionHeader::deserialize(&data[offset..])?;
87            headers.push(section_header);
88            offset += size;
89        }
90
91        // Last two sections must be symbol table and relocation table
92        let section_count = headers.len();
93        if section_count < 2 {
94            return Err(SerializationError::InvalidData);
95        }
96        if !matches!(headers[section_count - 2], SectionHeader::SymbolTable(_)) {
97            return Err(SerializationError::InvalidData);
98        }
99        if !matches!(
100            headers[section_count - 1],
101            SectionHeader::RelocationTable(_)
102        ) {
103            return Err(SerializationError::InvalidData);
104        }
105
106        // Ensure no other symbol/relocation table sections exist
107        if headers[..section_count - 2].iter().any(|h| {
108            matches!(
109                h,
110                SectionHeader::SymbolTable(_) | SectionHeader::RelocationTable(_)
111            )
112        }) {
113            return Err(SerializationError::InvalidData);
114        }
115
116        // Calculate offsets to symbol and relocation tables
117        let mut section_data_offset = offset;
118        for header in &headers[..section_count - 2] {
119            section_data_offset += header.section_size() as usize;
120        }
121
122        // Load symbol and relocation tables first
123        let symbol_offset = section_data_offset;
124        let (_, symbol_table) = SymbolTable::deserialize_section(
125            match &headers[section_count - 2] {
126                SectionHeader::SymbolTable(h) => h,
127                _ => unreachable!(),
128            },
129            &data[symbol_offset..],
130        )?;
131
132        let relocation_offset = symbol_offset + headers[section_count - 2].section_size() as usize;
133        let (_, relocation_table) = RelocationTable::deserialize(
134            match &headers[section_count - 1] {
135                SectionHeader::RelocationTable(h) => h,
136                _ => unreachable!(),
137            },
138            &data[relocation_offset..],
139        )?;
140
141        // Process regular sections
142        let mut sections = Vec::new();
143        let mut current_offset = offset;
144
145        for (idx, section_header) in headers[..section_count - 2].iter().enumerate() {
146            match section_header {
147                SectionHeader::Text(_) => {
148                    let symbols = symbol_table.get_symbols(idx as u32);
149                    let relocations = relocation_table.get_relocations(idx as u32);
150                    let (size, section) = Section::deserialize(
151                        section_header,
152                        &data[current_offset..],
153                        symbols,
154                        relocations,
155                    )?;
156                    sections.push(section);
157                    current_offset += size;
158                }
159                _ => return Err(SerializationError::InvalidData),
160            }
161        }
162
163        Ok((
164            relocation_offset + headers[section_count - 1].section_size() as usize,
165            ObjectFile {
166                architecture: header.architecture,
167                sections,
168            },
169        ))
170    }
171}
172
173impl ObjectFile {
174    pub fn new(architecture: Architecture) -> Self {
175        ObjectFile {
176            architecture,
177            sections: Vec::new(),
178        }
179    }
180
181    pub fn with_sections(architecture: Architecture, sections: Vec<Section>) -> Self {
182        ObjectFile {
183            architecture,
184            sections,
185        }
186    }
187
188    pub fn add_section(&mut self, section: Section) {
189        self.sections.push(section);
190    }
191
192    pub fn sections(self) -> Vec<Section> {
193        self.sections
194    }
195
196    pub fn architecture(&self) -> Architecture {
197        self.architecture
198    }
199
200    pub fn merge(&mut self, other: ObjectFile) {
201        if self.architecture != other.architecture {
202            panic!("Cannot merge object files with different architectures");
203        }
204        self.sections.extend(other.sections);
205    }
206}