1#[cfg(any(not(feature = "msvc"), not(feature = "gnu")))]
2use std::io::ErrorKind;
3use std::io::{Error, Seek, Write};
4
5use object::pe::*;
6
7#[cfg(any(feature = "msvc", feature = "gnu"))]
9mod ar;
10pub mod def;
12#[cfg(feature = "gnu")]
14mod gnu;
15#[cfg(feature = "msvc")]
17mod msvc;
18
19#[cfg(feature = "gnu")]
20use self::gnu::GnuImportLibrary;
21#[cfg(feature = "msvc")]
22use self::msvc::MsvcImportLibrary;
23use crate::def::ModuleDef;
24
25#[derive(Debug, Clone, Copy, PartialEq, Eq)]
27#[repr(u16)]
28pub enum MachineType {
29 I386 = IMAGE_FILE_MACHINE_I386,
31 ARMNT = IMAGE_FILE_MACHINE_ARMNT,
33 AMD64 = IMAGE_FILE_MACHINE_AMD64,
35 ARM64 = IMAGE_FILE_MACHINE_ARM64,
36}
37
38impl MachineType {
39 fn img_rel_relocation(&self) -> u16 {
40 match self {
41 Self::AMD64 => IMAGE_REL_AMD64_ADDR32NB,
42 Self::ARMNT => IMAGE_REL_ARM_ADDR32NB,
43 Self::ARM64 => IMAGE_REL_ARM64_ADDR32NB,
44 Self::I386 => IMAGE_REL_I386_DIR32NB,
45 }
46 }
47}
48
49#[derive(Debug)]
50struct ArchiveMember {
51 name: String,
52 data: Vec<u8>,
53 symbols: Vec<String>,
54}
55
56impl ArchiveMember {
57 #[cfg(any(feature = "msvc", feature = "gnu"))]
58 fn create_archive_entry(self) -> (ar::Header, ArchiveMember) {
59 let mut header =
60 ar::Header::new(self.name.to_string().into_bytes(), self.data.len() as u64);
61 header.set_mode(0o644);
62 (header, self)
63 }
64}
65
66#[derive(Debug, Clone, Copy)]
68pub enum Flavor {
69 Msvc,
71 Gnu,
73}
74
75#[derive(Debug, Clone)]
77pub struct ImportLibrary {
78 def: ModuleDef,
79 machine: MachineType,
80 flavor: Flavor,
81}
82
83impl ImportLibrary {
84 pub fn new(def: &str, machine: MachineType, flavor: Flavor) -> Result<Self, Error> {
86 let def = ModuleDef::parse(def, machine)?;
87 Ok(Self::from_def(def, machine, flavor))
88 }
89
90 pub fn from_def(mut def: ModuleDef, machine: MachineType, flavor: Flavor) -> Self {
92 for export in &mut def.exports {
96 if let Some(ext_name) = export.ext_name.take() {
97 export.name = ext_name;
98 }
99 }
100 ImportLibrary {
103 def,
104 machine,
105 flavor,
106 }
107 }
108
109 pub fn import_name(&self) -> &str {
111 &self.def.import_name
112 }
113
114 pub fn write_to<W: Write + Seek>(self, writer: &mut W) -> Result<(), Error> {
116 match self.flavor {
117 #[cfg(feature = "msvc")]
118 Flavor::Msvc => MsvcImportLibrary::new(self.def, self.machine).write_to(writer),
119 #[cfg(not(feature = "msvc"))]
120 Flavor::Msvc => Err(Error::new(
121 ErrorKind::Unsupported,
122 "MSVC import library unsupported, enable 'msvc' feature to use it",
123 )),
124 #[cfg(feature = "gnu")]
125 Flavor::Gnu => GnuImportLibrary::new(self.def, self.machine).write_to(writer),
126 #[cfg(not(feature = "gnu"))]
127 Flavor::Gnu => Err(Error::new(
128 ErrorKind::Unsupported,
129 "GNU import library unsupported, enable 'gnu' feature to use it",
130 )),
131 }
132 }
133}