@@ -5,8 +5,10 @@ use std::process::Command;
55
66use ar_archive_writer:: { ArchiveKind , COFFShortExport , MachineTypes } ;
77use common:: { create_archive_with_ar_archive_writer, create_archive_with_llvm_ar} ;
8+ use object:: coff:: CoffHeader ;
9+ use object:: pe:: ImageFileHeader ;
810use object:: read:: archive:: ArchiveFile ;
9- use object:: { Architecture , SubArchitecture } ;
11+ use object:: { bytes_of , Architecture , Object , SubArchitecture , U32Bytes } ;
1012use pretty_assertions:: assert_eq;
1113
1214mod 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