Skip to content

Commit 32d9046

Browse files
committed
Test optional COMDAT section for import libraries
1 parent 33dbe5f commit 32d9046

File tree

1 file changed

+77
-4
lines changed

1 file changed

+77
-4
lines changed

tests/import_library.rs

Lines changed: 77 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ use std::process::Command;
55

66
use ar_archive_writer::{ArchiveKind, COFFShortExport, MachineTypes};
77
use common::{create_archive_with_ar_archive_writer, create_archive_with_llvm_ar};
8+
use object::coff::CoffHeader;
9+
use object::pe::ImageFileHeader;
810
use object::read::archive::ArchiveFile;
9-
use object::{Architecture, SubArchitecture};
11+
use object::{bytes_of, Architecture, Object, SubArchitecture, U32Bytes};
1012
use pretty_assertions::assert_eq;
1113

1214
mod common;
@@ -99,6 +101,7 @@ fn create_import_library_with_ar_archive_writer(
99101
temp_dir: &Path,
100102
machine_type: MachineTypes,
101103
mingw: bool,
104+
comdat: bool,
102105
) -> Vec<u8> {
103106
let mut output_bytes = Cursor::new(Vec::new());
104107
ar_archive_writer::write_import_library(
@@ -107,6 +110,7 @@ fn create_import_library_with_ar_archive_writer(
107110
&get_members(machine_type),
108111
machine_type,
109112
mingw,
113+
comdat,
110114
)
111115
.unwrap();
112116

@@ -129,7 +133,7 @@ fn compare_to_lib() {
129133
let temp_dir = common::create_tmp_dir("import_library_compare_to_lib");
130134

131135
let archive_writer_bytes =
132-
create_import_library_with_ar_archive_writer(&temp_dir, machine_type, false);
136+
create_import_library_with_ar_archive_writer(&temp_dir, machine_type, false, false);
133137

134138
let llvm_lib_bytes = {
135139
let machine_arg = match machine_type {
@@ -164,6 +168,11 @@ fn compare_to_lib() {
164168
llvm_lib_bytes, archive_writer_bytes,
165169
"Import library differs. Machine type: {machine_type:?}",
166170
);
171+
172+
compare_comdat(
173+
&create_import_library_with_ar_archive_writer(&temp_dir, machine_type, false, true),
174+
&llvm_lib_bytes,
175+
);
167176
}
168177
}
169178

@@ -178,7 +187,7 @@ fn compare_to_dlltool() {
178187
let temp_dir = common::create_tmp_dir("import_library_compare_to_dlltool");
179188

180189
let archive_writer_bytes =
181-
create_import_library_with_ar_archive_writer(&temp_dir, machine_type, true);
190+
create_import_library_with_ar_archive_writer(&temp_dir, machine_type, true, false);
182191

183192
let llvm_lib_bytes = {
184193
let machine_arg = match machine_type {
@@ -215,6 +224,11 @@ fn compare_to_dlltool() {
215224
llvm_lib_bytes, archive_writer_bytes,
216225
"Import library differs. Machine type: {machine_type:?}",
217226
);
227+
228+
compare_comdat(
229+
&create_import_library_with_ar_archive_writer(&temp_dir, machine_type, true, true),
230+
&llvm_lib_bytes,
231+
);
218232
}
219233
}
220234

@@ -237,10 +251,11 @@ fn wrap_in_archive() {
237251
let mut import_lib_bytes = Cursor::new(Vec::new());
238252
ar_archive_writer::write_import_library(
239253
&mut import_lib_bytes,
240-
&temp_dir.join("MyLibrary.dll").to_string_lossy().to_string(),
254+
&temp_dir.join("MyLibrary.dll").to_string_lossy(),
241255
&get_members(machine_type),
242256
machine_type,
243257
false,
258+
false,
244259
)
245260
.unwrap();
246261
let import_lib_bytes = import_lib_bytes.into_inner();
@@ -281,3 +296,61 @@ fn wrap_in_archive() {
281296
);
282297
}
283298
}
299+
300+
fn compare_comdat(archive_writer_bytes: &[u8], llvm_bytes: &[u8]) {
301+
let archive_writer = ArchiveFile::parse(archive_writer_bytes).unwrap();
302+
let llvm = ArchiveFile::parse(llvm_bytes).unwrap();
303+
304+
for (archive_member, llvm_member) in archive_writer.members().zip(llvm.members()) {
305+
let archive_member = archive_member.unwrap();
306+
let llvm_member = llvm_member.unwrap();
307+
308+
if archive_member.size() != llvm_member.size() {
309+
// Ensure that the member header is the same except for the file size.
310+
let mut llvm_file_header = *llvm_member.header().unwrap();
311+
llvm_file_header.size = *b"163 ";
312+
assert_eq!(
313+
bytes_of(archive_member.header().unwrap()),
314+
bytes_of(&llvm_file_header)
315+
);
316+
317+
// Ensure that the LLVM generated object contains .idata$3
318+
object::File::parse(llvm_member.data(llvm_bytes).unwrap())
319+
.unwrap()
320+
.section_by_name_bytes(b".idata$3")
321+
.unwrap();
322+
323+
// Ensure the COFF file headers are the same except for the symbol count.
324+
let llvm_data = llvm_member.data(llvm_bytes).unwrap();
325+
let archive_data = archive_member.data(archive_writer_bytes).unwrap();
326+
let mut offset = 0;
327+
let mut header = *ImageFileHeader::parse(llvm_data, &mut offset).unwrap();
328+
header.number_of_symbols = U32Bytes::from_bytes(3_u32.to_le_bytes());
329+
assert_eq!(
330+
&archive_data[..size_of::<ImageFileHeader>()],
331+
bytes_of(&header)
332+
);
333+
334+
// The rest of the object file will always be the same as `expected`
335+
// for all import files no matter the platform.
336+
let expected = [
337+
46, 105, 100, 97, 116, 97, 36, 51, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 60, 0, 0,
338+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 16, 48, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0,
339+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 105, 100, 97, 116, 97, 36, 51, 0, 0, 0, 0, 1,
340+
0, 0, 0, 3, 1, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,
341+
4, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 29, 0, 0, 0, 95, 95, 78, 85, 76, 76, 95,
342+
73, 77, 80, 79, 82, 84, 95, 68, 69, 83, 67, 82, 73, 80, 84, 79, 82, 0,
343+
];
344+
assert_eq!(&archive_data[size_of::<ImageFileHeader>()..], &expected);
345+
} else {
346+
assert_eq!(
347+
bytes_of(archive_member.header().unwrap()),
348+
bytes_of(llvm_member.header().unwrap())
349+
);
350+
assert_eq!(
351+
archive_member.data(archive_writer_bytes).unwrap(),
352+
llvm_member.data(llvm_bytes).unwrap()
353+
);
354+
}
355+
}
356+
}

0 commit comments

Comments
 (0)