pe_assembler/types/coff/mod.rs
1use gaia_binary::{LittleEndian, ReadBytesExt};
2use gaia_types::{helpers::Architecture, GaiaError};
3use serde::{Deserialize, Serialize};
4use std::io::Read;
5
6/// COFF file header structure
7///
8/// Contains basic information for the COFF (Common Object File Format) format,
9/// defining key information such as target machine type, number of sections, and timestamp.
10#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
11pub struct CoffHeader {
12 /// Target machine type, such as x86, x64, ARM, etc.
13 pub machine: u16,
14 /// Number of sections in the file
15 pub number_of_sections: u16,
16 /// Timestamp indicating when the file was created or linked
17 pub time_date_stamp: u32,
18 /// File offset of the symbol table, or 0 if none exists
19 pub pointer_to_symbol_table: u32,
20 /// Number of symbols in the symbol table
21 pub number_of_symbols: u32,
22 /// Size of the optional header in bytes
23 pub size_of_optional_header: u16,
24 /// File characteristics flags describing various attributes of the file
25 pub characteristics: u16,
26}
27
28impl CoffHeader {
29 /// Create a new COFF header with core fields
30 pub fn new(machine: u16, number_of_sections: u16) -> Self {
31 CoffHeader {
32 machine,
33 number_of_sections,
34 time_date_stamp: 0,
35 pointer_to_symbol_table: 0,
36 number_of_symbols: 0,
37 size_of_optional_header: 0,
38 characteristics: 0,
39 }
40 }
41
42 /// Set timestamp
43 pub fn with_timestamp(mut self, time_date_stamp: u32) -> Self {
44 self.time_date_stamp = time_date_stamp;
45 self
46 }
47
48 /// Set symbol table information
49 pub fn with_symbol_table(mut self, pointer_to_symbol_table: u32, number_of_symbols: u32) -> Self {
50 self.pointer_to_symbol_table = pointer_to_symbol_table;
51 self.number_of_symbols = number_of_symbols;
52 self
53 }
54
55 /// Set optional header size
56 pub fn with_optional_header_size(mut self, size_of_optional_header: u16) -> Self {
57 self.size_of_optional_header = size_of_optional_header;
58 self
59 }
60
61 /// Set file characteristics
62 pub fn with_characteristics(mut self, characteristics: u16) -> Self {
63 self.characteristics = characteristics;
64 self
65 }
66
67 pub fn read<R: Read>(mut reader: R) -> Result<Self, GaiaError> {
68 Ok(CoffHeader {
69 machine: reader.read_u16::<LittleEndian>()?,
70 number_of_sections: reader.read_u16::<LittleEndian>()?,
71 time_date_stamp: reader.read_u32::<LittleEndian>()?,
72 pointer_to_symbol_table: reader.read_u32::<LittleEndian>()?,
73 number_of_symbols: reader.read_u32::<LittleEndian>()?,
74 size_of_optional_header: reader.read_u16::<LittleEndian>()?,
75 characteristics: reader.read_u16::<LittleEndian>()?,
76 })
77 }
78
79 pub fn get_architecture(&self) -> Architecture {
80 match self.machine {
81 0x014C => Architecture::X86,
82 0x8664 => Architecture::X86_64,
83 0x0200 => Architecture::ARM32,
84 0xAA64 => Architecture::ARM64,
85 _ => Architecture::Unknown,
86 }
87 }
88}
89
90/// Section header structure
91///
92/// Contains metadata for a section in a COFF file, such as name, size,
93/// position, and attributes. This structure doesn't contain the actual data of the section.
94#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
95pub struct SectionHeader {
96 /// Section name, 8-byte ASCII string like ".text", ".data", etc.
97 pub name: [u8; 8],
98 /// Virtual size of the section in memory
99 pub virtual_size: u32,
100 /// Virtual address of the section (RVA) in memory
101 pub virtual_address: u32,
102 /// Size of raw data in the file
103 pub size_of_raw_data: u32,
104 /// File offset of the section
105 pub pointer_to_raw_data: u32,
106 /// File offset of the relocation table
107 pub pointer_to_relocations: u32,
108 /// File offset of the line numbers table
109 pub pointer_to_line_numbers: u32,
110 /// Number of relocation entries
111 pub number_of_relocations: u16,
112 /// Number of line number entries
113 pub number_of_line_numbers: u16,
114 /// Section characteristics flags describing attributes (read, write, execute, etc.)
115 pub characteristics: u32,
116}
117
118impl SectionHeader {
119 pub fn get_name(&self) -> &str {
120 unsafe {
121 let name = std::str::from_utf8_unchecked(&self.name);
122 name.trim_end_matches('\0')
123 }
124 }
125}
126
127/// COFF symbol table entry
128///
129/// Represents a symbol in a COFF object file, containing symbol name, value, section number, etc.
130/// Symbols can be functions, variables, labels, or other identifiers in the program.
131#[derive(Clone, Debug, Serialize, Deserialize)]
132pub struct CoffSymbol {
133 /// Symbol name, stored in the string table if length exceeds 8 bytes
134 pub name: String,
135 /// Symbol value, usually an address or offset
136 pub value: u32,
137 /// Section number where the symbol resides: 0 for undefined, -1 for absolute, -2 for debug
138 pub section_number: i16,
139 /// Symbol type, describing the basic type of the symbol
140 pub symbol_type: u16,
141 /// Storage class, describing the scope and lifetime of the symbol
142 pub storage_class: u8,
143 /// Number of auxiliary symbols
144 pub number_of_aux_symbols: u8,
145}
146
147/// COFF relocation item
148///
149/// Represents an item that requires address relocation at link time.
150/// Relocation is the process of converting relative addresses to absolute addresses.
151#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
152pub struct CoffRelocation {
153 /// Virtual address that needs relocation
154 pub virtual_address: u32,
155 /// Symbol table index pointing to the related symbol
156 pub symbol_table_index: u32,
157 /// Relocation type, defining how to perform the relocation
158 pub relocation_type: u16,
159}
160
161/// COFF section structure
162///
163/// Represents a section in a COFF object file, containing the section header and data.
164/// Similar to a PE section but used for object files instead of executables.
165#[derive(Clone, Debug, Serialize, Deserialize)]
166pub struct CoffSection {
167 /// Section header info
168 pub header: SectionHeader,
169 /// Raw data of the section
170 #[serde(skip_serializing_if = "Vec::is_empty")]
171 pub data: Vec<u8>,
172 /// Relocation table containing all relocation entries for this section
173 pub relocations: Vec<CoffRelocation>,
174}
175
176/// COFF object file structure
177///
178/// Represents a complete COFF object file, containing header, sections, symbol table, etc.
179/// COFF object files are intermediate files generated by compilers, containing unlinked code and data.
180#[derive(Clone, Debug, Serialize, Deserialize)]
181pub struct CoffObject {
182 /// COFF header info
183 pub header: CoffHeader,
184 /// Collection of all sections
185 pub sections: Vec<CoffSection>,
186 /// Symbol table containing all symbol info
187 pub symbols: Vec<CoffSymbol>,
188 /// String table for storing long symbol names
189 pub string_table: Vec<u8>,
190}
191
192/// Archive member header
193///
194/// Represents the header information for a member file in a static library.
195/// Static libraries are collections of object files, each member having its own header.
196#[derive(Clone, Debug, Serialize, Deserialize)]
197pub struct ArchiveMemberHeader {
198 /// Member file name
199 pub name: String,
200 /// File modification timestamp
201 pub timestamp: u32,
202 /// User ID
203 pub user_id: u16,
204 /// Group ID
205 pub group_id: u16,
206 /// File permission mode
207 pub mode: u32,
208 /// File size
209 pub size: u32,
210}
211
212/// Archive member
213///
214/// Represents a member in a static library, containing a header and data.
215/// Each member is typically a COFF object file.
216#[derive(Clone, Debug, Serialize, Deserialize)]
217pub struct ArchiveMember {
218 /// Member header info
219 pub header: ArchiveMemberHeader,
220 /// Member data, usually the content of a COFF object file
221 pub data: Vec<u8>,
222 /// Parsed COFF object (if successfully parsed)
223 pub coff_object: Option<CoffObject>,
224}
225
226/// Static library file structure
227///
228/// Represents a complete static library file (.lib), containing multiple object files.
229/// Static libraries pack multiple object files into one for easier distribution and linking.
230#[derive(Clone, Debug, Serialize, Deserialize)]
231pub struct StaticLibrary {
232 /// Library signature, usually "!<arch>\n"
233 pub signature: String,
234 /// Collection of all member files
235 pub members: Vec<ArchiveMember>,
236 /// Symbol index table for fast symbol lookup
237 pub symbol_index: Vec<(String, usize)>, // (symbol_name, member_index)
238}
239
240/// COFF file type enum
241///
242/// Distinguishes between different types of COFF-related file formats.
243#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
244pub enum CoffFileType {
245 /// COFF object file (.obj)
246 Object,
247 /// Static library file (.lib)
248 StaticLibrary,
249 /// PE executable file (.exe)
250 Executable,
251 /// PE dynamic library file (.dll)
252 DynamicLibrary,
253}
254
255/// COFF file info
256///
257/// Provides summary information for COFF-related files.
258#[derive(Clone, Debug, Serialize, Deserialize)]
259pub struct CoffInfo {
260 /// File type
261 pub file_type: CoffFileType,
262 /// Target architecture
263 pub target_arch: Architecture,
264 /// Number of sections
265 pub section_count: u16,
266 /// Number of symbols
267 pub symbol_count: u32,
268 /// File size
269 pub file_size: u64,
270 /// Timestamp
271 pub timestamp: u32,
272}