Backed out 5 changesets (bug 1890092, bug 1888683) for causing build bustages & crash...
[gecko.git] / third_party / rust / goblin / src / pe / optional_header.rs
blobb1d3192764ea95e67f3a17a04fb05eb3f25268c9
1 use crate::container;
2 use crate::error;
4 use crate::pe::data_directories;
6 use scroll::{ctx, Endian, LE};
7 use scroll::{Pread, Pwrite, SizeWith};
9 /// standard COFF fields
10 #[repr(C)]
11 #[derive(Debug, PartialEq, Copy, Clone, Default, Pread, Pwrite, SizeWith)]
12 pub struct StandardFields32 {
13     pub magic: u16,
14     pub major_linker_version: u8,
15     pub minor_linker_version: u8,
16     pub size_of_code: u32,
17     pub size_of_initialized_data: u32,
18     pub size_of_uninitialized_data: u32,
19     pub address_of_entry_point: u32,
20     pub base_of_code: u32,
21     /// absent in 64-bit PE32+
22     pub base_of_data: u32,
25 pub const SIZEOF_STANDARD_FIELDS_32: usize = 28;
27 /// standard 64-bit COFF fields
28 #[repr(C)]
29 #[derive(Debug, PartialEq, Copy, Clone, Default, Pread, Pwrite, SizeWith)]
30 pub struct StandardFields64 {
31     pub magic: u16,
32     pub major_linker_version: u8,
33     pub minor_linker_version: u8,
34     pub size_of_code: u32,
35     pub size_of_initialized_data: u32,
36     pub size_of_uninitialized_data: u32,
37     pub address_of_entry_point: u32,
38     pub base_of_code: u32,
41 pub const SIZEOF_STANDARD_FIELDS_64: usize = 24;
43 /// Unified 32/64-bit COFF fields
44 #[derive(Debug, PartialEq, Copy, Clone, Default)]
45 pub struct StandardFields {
46     pub magic: u16,
47     pub major_linker_version: u8,
48     pub minor_linker_version: u8,
49     pub size_of_code: u64,
50     pub size_of_initialized_data: u64,
51     pub size_of_uninitialized_data: u64,
52     pub address_of_entry_point: u64,
53     pub base_of_code: u64,
54     /// absent in 64-bit PE32+
55     pub base_of_data: u32,
58 impl From<StandardFields32> for StandardFields {
59     fn from(fields: StandardFields32) -> Self {
60         StandardFields {
61             magic: fields.magic,
62             major_linker_version: fields.major_linker_version,
63             minor_linker_version: fields.minor_linker_version,
64             size_of_code: u64::from(fields.size_of_code),
65             size_of_initialized_data: u64::from(fields.size_of_initialized_data),
66             size_of_uninitialized_data: u64::from(fields.size_of_uninitialized_data),
67             address_of_entry_point: u64::from(fields.address_of_entry_point),
68             base_of_code: u64::from(fields.base_of_code),
69             base_of_data: fields.base_of_data,
70         }
71     }
74 impl From<StandardFields64> for StandardFields {
75     fn from(fields: StandardFields64) -> Self {
76         StandardFields {
77             magic: fields.magic,
78             major_linker_version: fields.major_linker_version,
79             minor_linker_version: fields.minor_linker_version,
80             size_of_code: u64::from(fields.size_of_code),
81             size_of_initialized_data: u64::from(fields.size_of_initialized_data),
82             size_of_uninitialized_data: u64::from(fields.size_of_uninitialized_data),
83             address_of_entry_point: u64::from(fields.address_of_entry_point),
84             base_of_code: u64::from(fields.base_of_code),
85             base_of_data: 0,
86         }
87     }
90 /// Standard fields magic number for 32-bit binary
91 pub const MAGIC_32: u16 = 0x10b;
92 /// Standard fields magic number for 64-bit binary
93 pub const MAGIC_64: u16 = 0x20b;
95 /// Windows specific fields
96 #[repr(C)]
97 #[derive(Debug, PartialEq, Copy, Clone, Default, Pread, Pwrite, SizeWith)]
98 pub struct WindowsFields32 {
99     pub image_base: u32,
100     pub section_alignment: u32,
101     pub file_alignment: u32,
102     pub major_operating_system_version: u16,
103     pub minor_operating_system_version: u16,
104     pub major_image_version: u16,
105     pub minor_image_version: u16,
106     pub major_subsystem_version: u16,
107     pub minor_subsystem_version: u16,
108     pub win32_version_value: u32,
109     pub size_of_image: u32,
110     pub size_of_headers: u32,
111     pub check_sum: u32,
112     pub subsystem: u16,
113     pub dll_characteristics: u16,
114     pub size_of_stack_reserve: u32,
115     pub size_of_stack_commit: u32,
116     pub size_of_heap_reserve: u32,
117     pub size_of_heap_commit: u32,
118     pub loader_flags: u32,
119     pub number_of_rva_and_sizes: u32,
122 pub const SIZEOF_WINDOWS_FIELDS_32: usize = 68;
123 /// Offset of the `check_sum` field in [`WindowsFields32`]
124 pub const OFFSET_WINDOWS_FIELDS_32_CHECKSUM: usize = 36;
126 /// 64-bit Windows specific fields
127 #[repr(C)]
128 #[derive(Debug, PartialEq, Copy, Clone, Default, Pread, Pwrite, SizeWith)]
129 pub struct WindowsFields64 {
130     pub image_base: u64,
131     pub section_alignment: u32,
132     pub file_alignment: u32,
133     pub major_operating_system_version: u16,
134     pub minor_operating_system_version: u16,
135     pub major_image_version: u16,
136     pub minor_image_version: u16,
137     pub major_subsystem_version: u16,
138     pub minor_subsystem_version: u16,
139     pub win32_version_value: u32,
140     pub size_of_image: u32,
141     pub size_of_headers: u32,
142     pub check_sum: u32,
143     pub subsystem: u16,
144     pub dll_characteristics: u16,
145     pub size_of_stack_reserve: u64,
146     pub size_of_stack_commit: u64,
147     pub size_of_heap_reserve: u64,
148     pub size_of_heap_commit: u64,
149     pub loader_flags: u32,
150     pub number_of_rva_and_sizes: u32,
153 pub const SIZEOF_WINDOWS_FIELDS_64: usize = 88;
154 /// Offset of the `check_sum` field in [`WindowsFields64`]
155 pub const OFFSET_WINDOWS_FIELDS_64_CHECKSUM: usize = 40;
157 // /// Generic 32/64-bit Windows specific fields
158 // #[derive(Debug, PartialEq, Copy, Clone, Default)]
159 // pub struct WindowsFields {
160 //     pub image_base: u64,
161 //     pub section_alignment: u32,
162 //     pub file_alignment: u32,
163 //     pub major_operating_system_version: u16,
164 //     pub minor_operating_system_version: u16,
165 //     pub major_image_version: u16,
166 //     pub minor_image_version: u16,
167 //     pub major_subsystem_version: u16,
168 //     pub minor_subsystem_version: u16,
169 //     pub win32_version_value: u32,
170 //     pub size_of_image: u32,
171 //     pub size_of_headers: u32,
172 //     pub check_sum: u32,
173 //     pub subsystem: u16,
174 //     pub dll_characteristics: u16,
175 //     pub size_of_stack_reserve: u64,
176 //     pub size_of_stack_commit:  u64,
177 //     pub size_of_heap_reserve:  u64,
178 //     pub size_of_heap_commit:   u64,
179 //     pub loader_flags: u32,
180 //     pub number_of_rva_and_sizes: u32,
181 // }
183 impl From<WindowsFields32> for WindowsFields {
184     fn from(windows: WindowsFields32) -> Self {
185         WindowsFields {
186             image_base: u64::from(windows.image_base),
187             section_alignment: windows.section_alignment,
188             file_alignment: windows.file_alignment,
189             major_operating_system_version: windows.major_operating_system_version,
190             minor_operating_system_version: windows.minor_operating_system_version,
191             major_image_version: windows.major_image_version,
192             minor_image_version: windows.minor_image_version,
193             major_subsystem_version: windows.major_subsystem_version,
194             minor_subsystem_version: windows.minor_subsystem_version,
195             win32_version_value: windows.win32_version_value,
196             size_of_image: windows.size_of_image,
197             size_of_headers: windows.size_of_headers,
198             check_sum: windows.check_sum,
199             subsystem: windows.subsystem,
200             dll_characteristics: windows.dll_characteristics,
201             size_of_stack_reserve: u64::from(windows.size_of_stack_reserve),
202             size_of_stack_commit: u64::from(windows.size_of_stack_commit),
203             size_of_heap_reserve: u64::from(windows.size_of_heap_reserve),
204             size_of_heap_commit: u64::from(windows.size_of_heap_commit),
205             loader_flags: windows.loader_flags,
206             number_of_rva_and_sizes: windows.number_of_rva_and_sizes,
207         }
208     }
211 // impl From<WindowsFields32> for WindowsFields {
212 //     fn from(windows: WindowsFields32) -> Self {
213 //         WindowsFields {
214 //             image_base: windows.image_base,
215 //             section_alignment: windows.section_alignment,
216 //             file_alignment: windows.file_alignment,
217 //             major_operating_system_version: windows.major_operating_system_version,
218 //             minor_operating_system_version: windows.minor_operating_system_version,
219 //             major_image_version: windows.major_image_version,
220 //             minor_image_version: windows.minor_image_version,
221 //             major_subsystem_version: windows.major_subsystem_version,
222 //             minor_subsystem_version: windows.minor_subsystem_version,
223 //             win32_version_value: windows.win32_version_value,
224 //             size_of_image: windows.size_of_image,
225 //             size_of_headers: windows.size_of_headers,
226 //             check_sum: windows.check_sum,
227 //             subsystem: windows.subsystem,
228 //             dll_characteristics: windows.dll_characteristics,
229 //             size_of_stack_reserve: windows.size_of_stack_reserve,
230 //             size_of_stack_commit: windows.size_of_stack_commit,
231 //             size_of_heap_reserve: windows.size_of_heap_reserve,
232 //             size_of_heap_commit: windows.size_of_heap_commit,
233 //             loader_flags: windows.loader_flags,
234 //             number_of_rva_and_sizes: windows.number_of_rva_and_sizes,
235 //         }
236 //     }
237 // }
239 pub type WindowsFields = WindowsFields64;
241 #[derive(Debug, PartialEq, Copy, Clone)]
242 pub struct OptionalHeader {
243     pub standard_fields: StandardFields,
244     pub windows_fields: WindowsFields,
245     pub data_directories: data_directories::DataDirectories,
248 impl OptionalHeader {
249     pub fn container(&self) -> error::Result<container::Container> {
250         match self.standard_fields.magic {
251             MAGIC_32 => Ok(container::Container::Little),
252             MAGIC_64 => Ok(container::Container::Big),
253             magic => Err(error::Error::BadMagic(u64::from(magic))),
254         }
255     }
258 impl<'a> ctx::TryFromCtx<'a, Endian> for OptionalHeader {
259     type Error = crate::error::Error;
260     fn try_from_ctx(bytes: &'a [u8], _: Endian) -> error::Result<(Self, usize)> {
261         let magic = bytes.pread_with::<u16>(0, LE)?;
262         let offset = &mut 0;
263         let (standard_fields, windows_fields): (StandardFields, WindowsFields) = match magic {
264             MAGIC_32 => {
265                 let standard_fields = bytes.gread_with::<StandardFields32>(offset, LE)?.into();
266                 let windows_fields = bytes.gread_with::<WindowsFields32>(offset, LE)?.into();
267                 (standard_fields, windows_fields)
268             }
269             MAGIC_64 => {
270                 let standard_fields = bytes.gread_with::<StandardFields64>(offset, LE)?.into();
271                 let windows_fields = bytes.gread_with::<WindowsFields64>(offset, LE)?;
272                 (standard_fields, windows_fields)
273             }
274             _ => return Err(error::Error::BadMagic(u64::from(magic))),
275         };
276         let data_directories = data_directories::DataDirectories::parse(
277             &bytes,
278             windows_fields.number_of_rva_and_sizes as usize,
279             offset,
280         )?;
281         Ok((
282             OptionalHeader {
283                 standard_fields,
284                 windows_fields,
285                 data_directories,
286             },
287             0,
288         )) // TODO: FIXME
289     }
292 #[cfg(test)]
293 mod tests {
294     use super::*;
295     #[test]
296     fn sizeof_standards32() {
297         assert_eq!(
298             ::std::mem::size_of::<StandardFields32>(),
299             SIZEOF_STANDARD_FIELDS_32
300         );
301     }
302     #[test]
303     fn sizeof_windows32() {
304         assert_eq!(
305             ::std::mem::size_of::<WindowsFields32>(),
306             SIZEOF_WINDOWS_FIELDS_32
307         );
308     }
309     #[test]
310     fn sizeof_standards64() {
311         assert_eq!(
312             ::std::mem::size_of::<StandardFields64>(),
313             SIZEOF_STANDARD_FIELDS_64
314         );
315     }
316     #[test]
317     fn sizeof_windows64() {
318         assert_eq!(
319             ::std::mem::size_of::<WindowsFields64>(),
320             SIZEOF_WINDOWS_FIELDS_64
321         );
322     }