1use std::io::{Error, Seek, Write};
2use std::mem::size_of;
3
4use memoffset::offset_of;
5use object::endian::{LittleEndian as LE, U16Bytes, U32Bytes, U16, U32};
6use object::pe::*;
7use object::pod::bytes_of;
8
9use crate::def::{ModuleDef, ShortExport};
10use crate::{ar, ArchiveMember, MachineType};
11
12const NULL_IMPORT_DESCRIPTOR_SYMBOL_NAME: &str = "__NULL_IMPORT_DESCRIPTOR";
13
14#[derive(Debug, Clone, Copy)]
15#[repr(u16)]
16enum ImportType {
17 Code,
19 Data,
21 Const,
23}
24
25impl ShortExport {
26 fn import_type(&self) -> ImportType {
27 if self.data {
28 ImportType::Data
29 } else if self.constant {
30 ImportType::Const
31 } else {
32 ImportType::Code
33 }
34 }
35}
36
37#[derive(Debug, Clone, Copy)]
38#[repr(u16)]
39enum ImportNameType {
40 Ordinal = IMPORT_OBJECT_ORDINAL,
45 Name = IMPORT_OBJECT_NAME,
47 NameNoPrefix = IMPORT_OBJECT_NAME_NO_PREFIX,
50 NameUndecorate = IMPORT_OBJECT_NAME_UNDECORATE,
53}
54
55impl MachineType {
56 fn is_32bit(&self) -> bool {
57 matches!(self, Self::ARMNT | Self::I386)
58 }
59}
60
61#[derive(Debug, Clone)]
63pub struct MsvcImportLibrary {
64 def: ModuleDef,
65 machine: MachineType,
66}
67
68impl MsvcImportLibrary {
69 pub fn new(mut def: ModuleDef, machine: MachineType) -> Self {
71 for export in &mut def.exports {
75 if let Some(ext_name) = export.ext_name.take() {
76 export.name = ext_name;
77 }
78 }
79 MsvcImportLibrary { def, machine }
82 }
83
84 fn get_name_type(&self, sym: &str, ext_name: &str) -> ImportNameType {
85 if ext_name.starts_with('_') && ext_name.contains('@') {
88 ImportNameType::Name
89 } else if sym != ext_name {
90 ImportNameType::NameUndecorate
91 } else if self.machine == MachineType::I386 && sym.starts_with('_') {
92 ImportNameType::NameNoPrefix
93 } else {
94 ImportNameType::Name
95 }
96 }
97
98 pub fn write_to<W: Write + Seek>(&self, writer: &mut W) -> Result<(), Error> {
100 let mut members = Vec::new();
101 let factory = ObjectFactory::new(&self.def.import_name, self.machine);
102
103 let import_descriptor = factory.create_import_descriptor();
104 members.push(import_descriptor.create_archive_entry());
105
106 let null_import_descriptor = factory.create_null_import_descriptor();
107 members.push(null_import_descriptor.create_archive_entry());
108
109 let null_thunk = factory.create_null_thunk();
110 members.push(null_thunk.create_archive_entry());
111
112 for export in &self.def.exports {
113 if export.private {
114 continue;
115 }
116 let sym = if export.symbol_name.is_empty() {
117 &export.name
118 } else {
119 &export.symbol_name
120 };
121 let name_type = if export.no_name {
122 ImportNameType::Ordinal
123 } else {
124 self.get_name_type(sym, &export.name)
125 };
126 let name = if let Some(ext_name) = &export.ext_name {
127 replace(sym, &export.name, ext_name)?
128 } else {
129 sym.to_string()
130 };
131
132 if !export.alias_target.is_empty() && name != export.alias_target {
133 let weak_non_imp = factory.create_weak_external(&export.alias_target, &name, false);
134 members.push(weak_non_imp.create_archive_entry());
135
136 let weak_imp = factory.create_weak_external(&export.alias_target, &name, true);
137 members.push(weak_imp.create_archive_entry());
138 }
139 let short_import =
140 factory.create_short_import(&name, export.ordinal, export.import_type(), name_type);
141 members.push(short_import.create_archive_entry());
142 }
143
144 let identifiers = members
145 .iter()
146 .map(|(header, _)| header.identifier().to_vec())
147 .collect();
148 let symbol_table: Vec<Vec<Vec<u8>>> = members
149 .iter()
150 .map(|(_, member)| {
151 member
152 .symbols
153 .iter()
154 .map(|s| s.to_string().into_bytes())
155 .collect::<Vec<Vec<u8>>>()
156 })
157 .collect();
158 let mut archive =
159 ar::GnuBuilder::new_with_symbol_table(writer, true, identifiers, symbol_table)?;
160 for (header, member) in members {
161 archive.append(&header, &member.data[..])?;
162 }
163 Ok(())
164 }
165}
166
167fn replace(sym: &str, from: &str, to: &str) -> Result<String, Error> {
168 use std::io::ErrorKind;
169
170 match sym.find(from) {
171 Some(pos) => return Ok(format!("{}{}{}", &sym[..pos], to, &sym[pos + from.len()..])),
172 None => {
173 if from.starts_with('_') && to.starts_with('_') {
174 if let Some(pos) = sym.find(&from[1..]) {
175 return Ok(format!(
176 "{}{}{}",
177 &sym[..pos],
178 &to[1..],
179 &sym[pos + from.len() - 1..]
180 ));
181 }
182 }
183 }
184 }
185 Err(Error::new(
186 ErrorKind::InvalidInput,
187 format!("{}: replacing '{}' with '{}' failed", sym, from, to),
188 ))
189}
190
191#[derive(Debug)]
196struct ObjectFactory<'a> {
197 machine: MachineType,
198 import_name: &'a str,
199 import_descriptor_symbol_name: String,
200 null_thunk_symbol_name: String,
201}
202
203impl<'a> ObjectFactory<'a> {
204 fn new(import_name: &'a str, machine: MachineType) -> Self {
205 let library = if import_name.ends_with(".dll") || import_name.ends_with(".exe") {
206 &import_name[..import_name.len() - 4]
207 } else {
208 import_name
209 };
210 Self {
211 machine,
212 import_name,
213 import_descriptor_symbol_name: format!("__IMPORT_DESCRIPTOR_{}", library),
214 null_thunk_symbol_name: format!("\x7f{}_NULL_THUNK_DATA", library),
215 }
216 }
217
218 fn write_string_table(buffer: &mut Vec<u8>, strings: &[&str]) {
219 let offset = buffer.len();
225
226 buffer.extend_from_slice(&[0, 0, 0, 0]);
229
230 for s in strings {
231 buffer.extend(s.as_bytes());
232 buffer.push(b'\0');
233 }
234
235 let size = (buffer.len() - offset) as u32;
237 buffer[offset..offset + 4].copy_from_slice(&size.to_le_bytes());
238 }
239
240 fn create_import_descriptor(&self) -> ArchiveMember {
245 const NUM_SECTIONS: usize = 2;
246 const NUM_SYMBOLS: usize = 7;
247 const NUM_RELOCATIONS: usize = 3;
248
249 let mut buffer = Vec::new();
250
251 let pointer_to_symbol_table = size_of::<ImageFileHeader>()
252 + NUM_SECTIONS * size_of::<ImageSectionHeader>()
253 + size_of::<ImageImportDescriptor>() + NUM_RELOCATIONS * size_of::<ImageRelocation>()
255 + self.import_name.len() + 1;
257 let characteristics = if self.machine.is_32bit() {
258 IMAGE_FILE_32BIT_MACHINE
259 } else {
260 0
261 };
262 let header = ImageFileHeader {
263 machine: U16::new(LE, self.machine as u16),
264 number_of_sections: U16::new(LE, NUM_SECTIONS as u16),
265 time_date_stamp: U32::new(LE, 0),
266 pointer_to_symbol_table: U32::new(LE, pointer_to_symbol_table as u32),
267 number_of_symbols: U32::new(LE, NUM_SYMBOLS as u32),
268 size_of_optional_header: U16::new(LE, 0),
269 characteristics: U16::new(LE, characteristics),
270 };
271 buffer.extend_from_slice(bytes_of(&header));
272
273 let section_header_table = [
275 ImageSectionHeader {
276 name: [b'.', b'i', b'd', b'a', b't', b'a', b'$', b'2'],
277 virtual_size: U32::new(LE, 0),
278 virtual_address: U32::new(LE, 0),
279 size_of_raw_data: U32::new(LE, size_of::<ImageImportDescriptor>() as _),
280 pointer_to_raw_data: U32::new(
281 LE,
282 (size_of::<ImageFileHeader>() + NUM_SECTIONS * size_of::<ImageSectionHeader>())
283 as _,
284 ),
285 pointer_to_relocations: U32::new(
286 LE,
287 (size_of::<ImageFileHeader>()
288 + NUM_SECTIONS * size_of::<ImageSectionHeader>()
289 + size_of::<ImageImportDescriptor>()) as _,
290 ),
291 pointer_to_linenumbers: U32::new(LE, 0),
292 number_of_relocations: U16::new(LE, NUM_RELOCATIONS as _),
293 number_of_linenumbers: U16::new(LE, 0),
294 characteristics: U32::new(
295 LE,
296 IMAGE_SCN_ALIGN_4BYTES
297 | IMAGE_SCN_CNT_INITIALIZED_DATA
298 | IMAGE_SCN_MEM_READ
299 | IMAGE_SCN_MEM_WRITE,
300 ),
301 },
302 ImageSectionHeader {
303 name: [b'.', b'i', b'd', b'a', b't', b'a', b'$', b'6'],
304 virtual_size: U32::new(LE, 0),
305 virtual_address: U32::new(LE, 0),
306 size_of_raw_data: U32::new(LE, (self.import_name.len() + 1) as _),
307 pointer_to_raw_data: U32::new(
308 LE,
309 (size_of::<ImageFileHeader>()
310 + NUM_SECTIONS * size_of::<ImageSectionHeader>()
311 + size_of::<ImageImportDescriptor>()
312 + NUM_RELOCATIONS * size_of::<ImageRelocation>()) as _,
313 ),
314 pointer_to_relocations: U32::new(LE, 0),
315 pointer_to_linenumbers: U32::new(LE, 0),
316 number_of_relocations: U16::new(LE, 0),
317 number_of_linenumbers: U16::new(LE, 0),
318 characteristics: U32::new(
319 LE,
320 IMAGE_SCN_ALIGN_2BYTES
321 | IMAGE_SCN_CNT_INITIALIZED_DATA
322 | IMAGE_SCN_MEM_READ
323 | IMAGE_SCN_MEM_WRITE,
324 ),
325 },
326 ];
327 for section in section_header_table {
328 buffer.extend_from_slice(bytes_of(§ion));
329 }
330
331 let import_descriptor = ImageImportDescriptor {
333 original_first_thunk: U32Bytes::new(LE, 0),
334 time_date_stamp: U32Bytes::new(LE, 0),
335 forwarder_chain: U32Bytes::new(LE, 0),
336 name: U32Bytes::new(LE, 0),
337 first_thunk: U32Bytes::new(LE, 0),
338 };
339 buffer.extend_from_slice(bytes_of(&import_descriptor));
340
341 let relocation_table = [
342 ImageRelocation {
343 virtual_address: U32Bytes::new(LE, offset_of!(ImageImportDescriptor, name) as _),
344 symbol_table_index: U32Bytes::new(LE, 2),
345 typ: U16Bytes::new(LE, self.machine.img_rel_relocation()),
346 },
347 ImageRelocation {
348 virtual_address: U32Bytes::new(
349 LE,
350 offset_of!(ImageImportDescriptor, original_first_thunk) as _,
351 ),
352 symbol_table_index: U32Bytes::new(LE, 3),
353 typ: U16Bytes::new(LE, self.machine.img_rel_relocation()),
354 },
355 ImageRelocation {
356 virtual_address: U32Bytes::new(
357 LE,
358 offset_of!(ImageImportDescriptor, first_thunk) as _,
359 ),
360 symbol_table_index: U32Bytes::new(LE, 4),
361 typ: U16Bytes::new(LE, self.machine.img_rel_relocation()),
362 },
363 ];
364 for relocation in &relocation_table {
365 buffer.extend_from_slice(bytes_of(relocation));
366 }
367
368 buffer.extend_from_slice(self.import_name.as_bytes());
370 buffer.push(b'\0');
371
372 let sym5_offset =
374 (size_of::<u32>() + self.import_descriptor_symbol_name.len() + 1).to_le_bytes();
375 let sym6_offset = (size_of::<u32>()
376 + self.import_descriptor_symbol_name.len()
377 + 1
378 + NULL_IMPORT_DESCRIPTOR_SYMBOL_NAME.len()
379 + 1)
380 .to_le_bytes();
381 let symbol_table = [
382 ImageSymbol {
383 name: [0, 0, 0, 0, size_of::<u32>() as _, 0, 0, 0],
384 value: U32Bytes::new(LE, 0),
385 section_number: U16Bytes::new(LE, 1),
386 typ: U16Bytes::new(LE, 0),
387 storage_class: IMAGE_SYM_CLASS_EXTERNAL,
388 number_of_aux_symbols: 0,
389 },
390 ImageSymbol {
391 name: [b'.', b'i', b'd', b'a', b't', b'a', b'$', b'2'],
392 value: U32Bytes::new(LE, 0),
393 section_number: U16Bytes::new(LE, 1),
394 typ: U16Bytes::new(LE, 0),
395 storage_class: IMAGE_SYM_CLASS_SECTION,
396 number_of_aux_symbols: 0,
397 },
398 ImageSymbol {
399 name: [b'.', b'i', b'd', b'a', b't', b'a', b'$', b'6'],
400 value: U32Bytes::new(LE, 0),
401 section_number: U16Bytes::new(LE, 2),
402 typ: U16Bytes::new(LE, 0),
403 storage_class: IMAGE_SYM_CLASS_STATIC,
404 number_of_aux_symbols: 0,
405 },
406 ImageSymbol {
407 name: [b'.', b'i', b'd', b'a', b't', b'a', b'$', b'4'],
408 value: U32Bytes::new(LE, 0),
409 section_number: U16Bytes::new(LE, 0),
410 typ: U16Bytes::new(LE, 0),
411 storage_class: IMAGE_SYM_CLASS_SECTION,
412 number_of_aux_symbols: 0,
413 },
414 ImageSymbol {
415 name: [b'.', b'i', b'd', b'a', b't', b'a', b'$', b'5'],
416 value: U32Bytes::new(LE, 0),
417 section_number: U16Bytes::new(LE, 0),
418 typ: U16Bytes::new(LE, 0),
419 storage_class: IMAGE_SYM_CLASS_SECTION,
420 number_of_aux_symbols: 0,
421 },
422 ImageSymbol {
423 name: [
424 0,
425 0,
426 0,
427 0,
428 sym5_offset[0],
429 sym5_offset[1],
430 sym5_offset[2],
431 sym5_offset[3],
432 ],
433 value: U32Bytes::new(LE, 0),
434 section_number: U16Bytes::new(LE, 0),
435 typ: U16Bytes::new(LE, 0),
436 storage_class: IMAGE_SYM_CLASS_EXTERNAL,
437 number_of_aux_symbols: 0,
438 },
439 ImageSymbol {
440 name: [
441 0,
442 0,
443 0,
444 0,
445 sym6_offset[0],
446 sym6_offset[1],
447 sym6_offset[2],
448 sym6_offset[3],
449 ],
450 value: U32Bytes::new(LE, 0),
451 section_number: U16Bytes::new(LE, 0),
452 typ: U16Bytes::new(LE, 0),
453 storage_class: IMAGE_SYM_CLASS_EXTERNAL,
454 number_of_aux_symbols: 0,
455 },
456 ];
457 for table in &symbol_table {
458 buffer.extend_from_slice(bytes_of(table));
459 }
460
461 Self::write_string_table(
462 &mut buffer,
463 &[
464 &self.import_descriptor_symbol_name,
465 NULL_IMPORT_DESCRIPTOR_SYMBOL_NAME,
466 &self.null_thunk_symbol_name,
467 ],
468 );
469 ArchiveMember {
470 name: self.import_name.to_string(),
471 data: buffer,
472 symbols: vec![self.import_descriptor_symbol_name.to_string()],
473 }
474 }
475
476 fn create_null_import_descriptor(&self) -> ArchiveMember {
480 const NUM_SECTIONS: usize = 1;
481 const NUM_SYMBOLS: usize = 1;
482
483 let mut buffer = Vec::new();
484
485 let pointer_to_symbol_table = size_of::<ImageFileHeader>()
486 + NUM_SECTIONS * size_of::<ImageSectionHeader>()
487 + size_of::<ImageImportDescriptor>();
489 let characteristics = if self.machine.is_32bit() {
490 IMAGE_FILE_32BIT_MACHINE
491 } else {
492 0
493 };
494 let header = ImageFileHeader {
495 machine: U16::new(LE, self.machine as u16),
496 number_of_sections: U16::new(LE, NUM_SECTIONS as u16),
497 time_date_stamp: U32::new(LE, 0),
498 pointer_to_symbol_table: U32::new(LE, pointer_to_symbol_table as u32),
499 number_of_symbols: U32::new(LE, NUM_SYMBOLS as u32),
500 size_of_optional_header: U16::new(LE, 0),
501 characteristics: U16::new(LE, characteristics),
502 };
503 buffer.extend_from_slice(bytes_of(&header));
504
505 let section_header_table = ImageSectionHeader {
507 name: [b'.', b'i', b'd', b'a', b't', b'a', b'$', b'3'],
508 virtual_size: U32::new(LE, 0),
509 virtual_address: U32::new(LE, 0),
510 size_of_raw_data: U32::new(LE, size_of::<ImageImportDescriptor>() as _),
511 pointer_to_raw_data: U32::new(
512 LE,
513 (size_of::<ImageFileHeader>() + NUM_SECTIONS * size_of::<ImageSectionHeader>())
514 as _,
515 ),
516 pointer_to_relocations: U32::new(LE, 0),
517 pointer_to_linenumbers: U32::new(LE, 0),
518 number_of_relocations: U16::new(LE, 0),
519 number_of_linenumbers: U16::new(LE, 0),
520 characteristics: U32::new(
521 LE,
522 IMAGE_SCN_ALIGN_4BYTES
523 | IMAGE_SCN_CNT_INITIALIZED_DATA
524 | IMAGE_SCN_MEM_READ
525 | IMAGE_SCN_MEM_WRITE,
526 ),
527 };
528 buffer.extend_from_slice(bytes_of(§ion_header_table));
529
530 let import_descriptor = ImageImportDescriptor {
532 original_first_thunk: U32Bytes::new(LE, 0),
533 time_date_stamp: U32Bytes::new(LE, 0),
534 forwarder_chain: U32Bytes::new(LE, 0),
535 name: U32Bytes::new(LE, 0),
536 first_thunk: U32Bytes::new(LE, 0),
537 };
538 buffer.extend_from_slice(bytes_of(&import_descriptor));
539
540 let symbol_table = ImageSymbol {
542 name: [0, 0, 0, 0, size_of::<u32>() as _, 0, 0, 0],
543 value: U32Bytes::new(LE, 0),
544 section_number: U16Bytes::new(LE, 1),
545 typ: U16Bytes::new(LE, 0),
546 storage_class: IMAGE_SYM_CLASS_EXTERNAL,
547 number_of_aux_symbols: 0,
548 };
549 buffer.extend_from_slice(bytes_of(&symbol_table));
550
551 Self::write_string_table(&mut buffer, &[NULL_IMPORT_DESCRIPTOR_SYMBOL_NAME]);
552 ArchiveMember {
553 name: self.import_name.to_string(),
554 data: buffer,
555 symbols: vec![NULL_IMPORT_DESCRIPTOR_SYMBOL_NAME.to_string()],
556 }
557 }
558
559 fn create_null_thunk(&self) -> ArchiveMember {
563 const NUM_SECTIONS: usize = 2;
564 const NUM_SYMBOLS: usize = 1;
565
566 let mut buffer = Vec::new();
567
568 let va_size = if self.machine.is_32bit() { 4 } else { 8 };
569 let pointer_to_symbol_table = size_of::<ImageFileHeader>()
570 + NUM_SECTIONS * size_of::<ImageSectionHeader>()
571 + va_size
573 + va_size;
575 let characteristics = if self.machine.is_32bit() {
576 IMAGE_FILE_32BIT_MACHINE
577 } else {
578 0
579 };
580 let header = ImageFileHeader {
581 machine: U16::new(LE, self.machine as u16),
582 number_of_sections: U16::new(LE, NUM_SECTIONS as u16),
583 time_date_stamp: U32::new(LE, 0),
584 pointer_to_symbol_table: U32::new(LE, pointer_to_symbol_table as u32),
585 number_of_symbols: U32::new(LE, NUM_SYMBOLS as u32),
586 size_of_optional_header: U16::new(LE, 0),
587 characteristics: U16::new(LE, characteristics),
588 };
589 buffer.extend_from_slice(bytes_of(&header));
590
591 let align = if self.machine.is_32bit() {
593 IMAGE_SCN_ALIGN_4BYTES
594 } else {
595 IMAGE_SCN_ALIGN_8BYTES
596 };
597 let section_header_table = [
598 ImageSectionHeader {
599 name: [b'.', b'i', b'd', b'a', b't', b'a', b'$', b'5'],
600 virtual_size: U32::new(LE, 0),
601 virtual_address: U32::new(LE, 0),
602 size_of_raw_data: U32::new(LE, va_size as _),
603 pointer_to_raw_data: U32::new(
604 LE,
605 (size_of::<ImageFileHeader>() + NUM_SECTIONS * size_of::<ImageSectionHeader>())
606 as _,
607 ),
608 pointer_to_relocations: U32::new(LE, 0),
609 pointer_to_linenumbers: U32::new(LE, 0),
610 number_of_relocations: U16::new(LE, 0),
611 number_of_linenumbers: U16::new(LE, 0),
612 characteristics: U32::new(
613 LE,
614 align
615 | IMAGE_SCN_CNT_INITIALIZED_DATA
616 | IMAGE_SCN_MEM_READ
617 | IMAGE_SCN_MEM_WRITE,
618 ),
619 },
620 ImageSectionHeader {
621 name: [b'.', b'i', b'd', b'a', b't', b'a', b'$', b'4'],
622 virtual_size: U32::new(LE, 0),
623 virtual_address: U32::new(LE, 0),
624 size_of_raw_data: U32::new(LE, va_size as _),
625 pointer_to_raw_data: U32::new(
626 LE,
627 (size_of::<ImageFileHeader>()
628 + NUM_SECTIONS * size_of::<ImageSectionHeader>()
629 + va_size) as _,
630 ),
631 pointer_to_relocations: U32::new(LE, 0),
632 pointer_to_linenumbers: U32::new(LE, 0),
633 number_of_relocations: U16::new(LE, 0),
634 number_of_linenumbers: U16::new(LE, 0),
635 characteristics: U32::new(
636 LE,
637 align
638 | IMAGE_SCN_CNT_INITIALIZED_DATA
639 | IMAGE_SCN_MEM_READ
640 | IMAGE_SCN_MEM_WRITE,
641 ),
642 },
643 ];
644 for section in section_header_table {
645 buffer.extend_from_slice(bytes_of(§ion));
646 }
647
648 buffer.extend(0u32.to_le_bytes());
650 if !self.machine.is_32bit() {
651 buffer.extend(0u32.to_le_bytes());
652 }
653
654 buffer.extend(0u32.to_le_bytes());
656 if !self.machine.is_32bit() {
657 buffer.extend(0u32.to_le_bytes());
658 }
659
660 let symbol_table = ImageSymbol {
662 name: [0, 0, 0, 0, size_of::<u32>() as _, 0, 0, 0],
663 value: U32Bytes::new(LE, 0),
664 section_number: U16Bytes::new(LE, 1),
665 typ: U16Bytes::new(LE, 0),
666 storage_class: IMAGE_SYM_CLASS_EXTERNAL,
667 number_of_aux_symbols: 0,
668 };
669 buffer.extend_from_slice(bytes_of(&symbol_table));
670
671 Self::write_string_table(&mut buffer, &[&self.null_thunk_symbol_name]);
672 ArchiveMember {
673 name: self.import_name.to_string(),
674 data: buffer,
675 symbols: vec![self.null_thunk_symbol_name.to_string()],
676 }
677 }
678
679 fn create_short_import(
682 &self,
683 sym: &str,
684 ordinal: u16,
685 import_type: ImportType,
686 name_type: ImportNameType,
687 ) -> ArchiveMember {
688 let import_name_size = self.import_name.len() + sym.len() + 2;
690 let size = size_of::<ImportObjectHeader>() + import_name_size;
691 let mut buffer = Vec::with_capacity(size);
692
693 let import_header = ImportObjectHeader {
695 sig1: U16::new(LE, 0),
696 sig2: U16::new(LE, 0xFFFF),
697 version: U16::new(LE, 0),
698 machine: U16::new(LE, self.machine as _),
699 time_date_stamp: U32::new(LE, 0),
700 size_of_data: U32::new(LE, import_name_size as _),
701 ordinal_or_hint: if ordinal > 0 {
702 U16::new(LE, ordinal)
703 } else {
704 U16::new(LE, 0)
705 },
706 name_type: U16::new(LE, ((name_type as u16) << 2) | import_type as u16),
707 };
708 buffer.extend_from_slice(bytes_of(&import_header));
709
710 let symbols = if matches!(import_type, ImportType::Data) {
711 vec![format!("__imp_{}", sym)]
712 } else {
713 vec![format!("__imp_{}", sym), sym.to_string()]
714 };
715
716 buffer.extend(sym.as_bytes());
718 buffer.push(b'\0');
719 buffer.extend(self.import_name.as_bytes());
720 buffer.push(b'\0');
721
722 ArchiveMember {
723 name: self.import_name.to_string(),
724 data: buffer,
725 symbols,
726 }
727 }
728
729 fn create_weak_external(&self, sym: &str, weak: &str, imp: bool) -> ArchiveMember {
731 const NUM_SECTIONS: usize = 1;
732 const NUM_SYMBOLS: usize = 5;
733
734 let mut buffer = Vec::new();
735
736 let pointer_to_symbol_table =
737 size_of::<ImageFileHeader>() + NUM_SECTIONS * size_of::<ImageSectionHeader>();
738 let header = ImageFileHeader {
739 machine: U16::new(LE, self.machine as u16),
740 number_of_sections: U16::new(LE, NUM_SECTIONS as u16),
741 time_date_stamp: U32::new(LE, 0),
742 pointer_to_symbol_table: U32::new(LE, pointer_to_symbol_table as u32),
743 number_of_symbols: U32::new(LE, NUM_SYMBOLS as u32),
744 size_of_optional_header: U16::new(LE, 0),
745 characteristics: U16::new(LE, 0),
746 };
747 buffer.extend_from_slice(bytes_of(&header));
748
749 let section_header_table = ImageSectionHeader {
751 name: [b'.', b'd', b'r', b'e', b'c', b't', b'v', b'e'],
752 virtual_size: U32::new(LE, 0),
753 virtual_address: U32::new(LE, 0),
754 size_of_raw_data: U32::new(LE, 0),
755 pointer_to_raw_data: U32::new(LE, 0),
756 pointer_to_relocations: U32::new(LE, 0),
757 pointer_to_linenumbers: U32::new(LE, 0),
758 number_of_relocations: U16::new(LE, 0),
759 number_of_linenumbers: U16::new(LE, 0),
760 characteristics: U32::new(LE, IMAGE_SCN_LNK_INFO | IMAGE_SCN_LNK_REMOVE),
761 };
762 buffer.extend_from_slice(bytes_of(§ion_header_table));
763
764 let prefix = if imp { "__imp_" } else { "" };
766 let sym3_offset = (size_of::<u32>() + sym.len() + prefix.len() + 1).to_le_bytes();
767 let symbol_table = [
768 ImageSymbol {
769 name: [b'@', b'c', b'o', b'm', b'p', b'.', b'i', b'd'],
770 value: U32Bytes::new(LE, 0),
771 section_number: U16Bytes::new(LE, 0xFFFF),
772 typ: U16Bytes::new(LE, 0),
773 storage_class: IMAGE_SYM_CLASS_STATIC,
774 number_of_aux_symbols: 0,
775 },
776 ImageSymbol {
777 name: [b'@', b'f', b'e', b'a', b't', b'.', b'0', b'0'],
778 value: U32Bytes::new(LE, 0),
779 section_number: U16Bytes::new(LE, 0xFFFF),
780 typ: U16Bytes::new(LE, 0),
781 storage_class: IMAGE_SYM_CLASS_STATIC,
782 number_of_aux_symbols: 0,
783 },
784 ImageSymbol {
785 name: [0, 0, 0, 0, size_of::<u32>() as _, 0, 0, 0],
786 value: U32Bytes::new(LE, 0),
787 section_number: U16Bytes::new(LE, 0),
788 typ: U16Bytes::new(LE, 0),
789 storage_class: IMAGE_SYM_CLASS_EXTERNAL,
790 number_of_aux_symbols: 0,
791 },
792 ImageSymbol {
793 name: [
794 0,
795 0,
796 0,
797 0,
798 sym3_offset[0],
799 sym3_offset[1],
800 sym3_offset[2],
801 sym3_offset[3],
802 ],
803 value: U32Bytes::new(LE, 0),
804 section_number: U16Bytes::new(LE, 0),
805 typ: U16Bytes::new(LE, 0),
806 storage_class: IMAGE_SYM_CLASS_WEAK_EXTERNAL,
807 number_of_aux_symbols: 1,
808 },
809 ImageSymbol {
810 name: [2, 0, 0, 0, IMAGE_WEAK_EXTERN_SEARCH_ALIAS as u8, 0, 0, 0],
811 value: U32Bytes::new(LE, 0),
812 section_number: U16Bytes::new(LE, 0),
813 typ: U16Bytes::new(LE, 0),
814 storage_class: IMAGE_SYM_CLASS_NULL,
815 number_of_aux_symbols: 0,
816 },
817 ];
818 for table in &symbol_table {
819 buffer.extend_from_slice(bytes_of(table));
820 }
821
822 Self::write_string_table(
824 &mut buffer,
825 &[
826 &format!("{}{}", prefix, sym),
827 &format!("{}{}", prefix, weak),
828 ],
829 );
830 ArchiveMember {
831 name: self.import_name.to_string(),
832 data: buffer,
833 symbols: Vec::new(),
834 }
835 }
836}