Skip to content

Commit 58325ad

Browse files
committed
Implement ordinal / name-types
1 parent 50cbdc8 commit 58325ad

File tree

3 files changed

+100
-21
lines changed

3 files changed

+100
-21
lines changed

src/archive.rs

+28-6
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,36 @@ impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
2121
tmpdir: &Path,
2222
_is_direct_dependency: bool,
2323
) -> PathBuf {
24-
let mut import_names = Vec::new();
25-
for dll_import in dll_imports {
26-
import_names.push(dll_import.name.as_str());
27-
}
2824
let lib_path = tmpdir.join(format!("{lib_name}_import.lib"));
25+
26+
// todo: use the same DllImport type?
27+
let import_lib_imports = dll_imports
28+
.into_iter()
29+
.map(|import| crate::dll_import_lib::Import {
30+
symbol_name: import.name.to_string(),
31+
ordinal_or_hint: import.ordinal(),
32+
name_type: match import.import_name_type {
33+
Some(rustc_session::cstore::PeImportNameType::Ordinal(_)) => {
34+
crate::dll_import_lib::ImportNameType::Ordinal
35+
}
36+
None | Some(rustc_session::cstore::PeImportNameType::Decorated) => {
37+
crate::dll_import_lib::ImportNameType::Name
38+
}
39+
Some(rustc_session::cstore::PeImportNameType::NoPrefix) => {
40+
crate::dll_import_lib::ImportNameType::NameNoPrefix
41+
}
42+
Some(rustc_session::cstore::PeImportNameType::Undecorated) => {
43+
crate::dll_import_lib::ImportNameType::NameUndecorate
44+
}
45+
},
46+
import_type: crate::dll_import_lib::ImportType::Code,
47+
})
48+
.collect::<Vec<_>>();
49+
50+
let import_lib = crate::dll_import_lib::generate(lib_name, &import_lib_imports);
51+
2952
// todo: emit session error instead of expects
30-
fs::write(&lib_path, crate::dll_import_lib::generate(lib_name, &import_names))
31-
.expect("failed to write import library");
53+
fs::write(&lib_path, import_lib).expect("failed to write import library");
3254

3355
lib_path
3456
}

src/dll_import_lib/coff.rs

+67-11
Original file line numberDiff line numberDiff line change
@@ -89,25 +89,81 @@ pub(crate) struct ImportObjectHeaderUnaligned {
8989
/// - have no padding
9090
unsafe impl object::pod::Pod for ImportObjectHeaderUnaligned {}
9191

92-
pub(crate) fn write_short_import(
93-
data: &mut DataWriter,
94-
dll_name: &str,
95-
name: &&str,
96-
ordinal_or_hint: Option<std::primitive::u16>,
97-
) {
92+
/// The IMPORT_OBJECT_* constants used to find the exported value in the DLL.
93+
pub(crate) enum ImportNameType {
94+
/// No import name, import by ordinal only.
95+
Ordinal,
96+
/// Import name == public symbol name.
97+
Name,
98+
/// Import name == public symbol name skipping leading ?, @, or optionally _.
99+
NameNoPrefix,
100+
/// Import name == public symbol name skipping leading ?, @, or optionally _ and truncating at first @.
101+
NameUndecorate,
102+
/// Import name == a name is explicitly provided after the DLL name.
103+
NameExportAs { export_name: String },
104+
}
105+
106+
impl ImportNameType {
107+
fn as_u16(&self) -> u16 {
108+
match self {
109+
ImportNameType::Ordinal => IMPORT_OBJECT_ORDINAL,
110+
ImportNameType::Name => IMPORT_OBJECT_NAME,
111+
ImportNameType::NameNoPrefix => IMPORT_OBJECT_NAME_NO_PREFIX,
112+
ImportNameType::NameUndecorate => IMPORT_OBJECT_NAME_UNDECORATE,
113+
ImportNameType::NameExportAs { .. } => IMPORT_OBJECT_NAME_EXPORTAS,
114+
}
115+
}
116+
}
117+
118+
/// The IMPORT_OBJECT_* constants that defines how the import is linked, or in the words of the PE
119+
/// documentation:
120+
/// > These values are used to determine which section contributions must be generated by the tool
121+
/// > that uses the library if it must access that data.
122+
pub(crate) enum ImportType {
123+
Code,
124+
Data,
125+
Const,
126+
}
127+
128+
impl ImportType {
129+
fn as_u16(&self) -> u16 {
130+
match self {
131+
ImportType::Code => IMPORT_OBJECT_CODE,
132+
ImportType::Data => IMPORT_OBJECT_DATA,
133+
ImportType::Const => IMPORT_OBJECT_CONST,
134+
}
135+
}
136+
}
137+
138+
pub(crate) struct Import {
139+
pub(crate) symbol_name: String,
140+
pub(crate) name_type: ImportNameType,
141+
pub(crate) import_type: ImportType,
142+
pub(crate) ordinal_or_hint: Option<std::primitive::u16>,
143+
}
144+
145+
pub(crate) fn write_short_import(data: &mut DataWriter, dll_name: &str, import: &Import) {
146+
let mut size_of_data = import.symbol_name.len() + 1 + dll_name.len() + 1;
147+
if let ImportNameType::NameExportAs { export_name } = &import.name_type {
148+
size_of_data += export_name.len() + 1;
149+
}
150+
98151
data.write_pod(&ImportObjectHeaderUnaligned {
99152
sig1: u16(IMAGE_FILE_MACHINE_UNKNOWN),
100153
sig2: u16(IMPORT_OBJECT_HDR_SIG2),
101154
version: u16(0),
102155
machine: u16(IMAGE_FILE_MACHINE_AMD64),
103156
time_date_stamp: u32(0),
104-
size_of_data: u32((name.len() + 1 + dll_name.len() + 1) as u32),
105-
ordinal_or_hint: u16(ordinal_or_hint.unwrap_or_default()),
106-
name_type: u16(IMPORT_OBJECT_CODE << IMPORT_OBJECT_TYPE_SHIFT
107-
| IMPORT_OBJECT_NAME << IMPORT_OBJECT_NAME_SHIFT),
157+
size_of_data: u32(size_of_data as u32),
158+
ordinal_or_hint: u16(import.ordinal_or_hint.unwrap_or_default()),
159+
name_type: u16(import.import_type.as_u16() << IMPORT_OBJECT_TYPE_SHIFT
160+
| import.name_type.as_u16() << IMPORT_OBJECT_NAME_SHIFT),
108161
});
109-
data.write_c_str(name);
162+
data.write_c_str(&import.symbol_name);
110163
data.write_c_str(dll_name);
164+
if let ImportNameType::NameExportAs { export_name } = &import.name_type {
165+
data.write_c_str(&export_name);
166+
}
111167
}
112168

113169
pub(crate) fn write_import_descriptor(

src/dll_import_lib/mod.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@ use object::{Object, ObjectSymbol};
1111

1212
use data::DataWriter;
1313

14+
mod coff;
1415
mod data;
1516
mod string_table;
1617

17-
mod coff;
18+
pub(crate) use coff::{Import, ImportNameType, ImportType};
1819

19-
pub(crate) fn generate(dll_name: &str, import_names: &[&str]) -> Vec<u8> {
20+
pub(crate) fn generate(dll_name: &str, imports: &[Import]) -> Vec<u8> {
2021
let mut members = Vec::new();
2122

2223
// foo.dll => foo so we can construct the import descriptor symbol.
@@ -98,9 +99,9 @@ pub(crate) fn generate(dll_name: &str, import_names: &[&str]) -> Vec<u8> {
9899
}
99100

100101
// short import object members
101-
for name in import_names.iter() {
102+
for import in imports {
102103
let mut buf = DataWriter::new();
103-
coff::write_short_import(&mut buf, dll_name, name, None);
104+
coff::write_short_import(&mut buf, dll_name, &import);
104105
members.push(ar_archive_writer::NewArchiveMember {
105106
member_name: dll_name.to_string(),
106107
buf: Box::new(buf.into_data()),

0 commit comments

Comments
 (0)