@@ -10,12 +10,13 @@ use std::path::PathBuf;
10
10
use std:: str:: from_utf8;
11
11
12
12
use object:: pe:: {
13
- ImageFileHeader , ImageImportDescriptor , ImageRelocation , ImageSectionHeader , ImageSymbol ,
14
- ImportObjectHeader , IMAGE_FILE_32BIT_MACHINE , IMAGE_REL_AMD64_ADDR32NB ,
15
- IMAGE_REL_ARM64_ADDR32NB , IMAGE_REL_ARM_ADDR32NB , IMAGE_REL_I386_DIR32NB ,
16
- IMAGE_SCN_ALIGN_2BYTES , IMAGE_SCN_ALIGN_4BYTES , IMAGE_SCN_ALIGN_8BYTES ,
17
- IMAGE_SCN_CNT_INITIALIZED_DATA , IMAGE_SCN_LNK_INFO , IMAGE_SCN_LNK_REMOVE , IMAGE_SCN_MEM_READ ,
18
- IMAGE_SCN_MEM_WRITE , IMAGE_SYM_CLASS_EXTERNAL , IMAGE_SYM_CLASS_NULL , IMAGE_SYM_CLASS_SECTION ,
13
+ ImageAuxSymbolSection , ImageFileHeader , ImageImportDescriptor , ImageRelocation ,
14
+ ImageSectionHeader , ImageSymbol , ImportObjectHeader , IMAGE_COMDAT_SELECT_ANY ,
15
+ IMAGE_FILE_32BIT_MACHINE , IMAGE_REL_AMD64_ADDR32NB , IMAGE_REL_ARM64_ADDR32NB ,
16
+ IMAGE_REL_ARM_ADDR32NB , IMAGE_REL_I386_DIR32NB , IMAGE_SCN_ALIGN_2BYTES , IMAGE_SCN_ALIGN_4BYTES ,
17
+ IMAGE_SCN_ALIGN_8BYTES , IMAGE_SCN_CNT_INITIALIZED_DATA , IMAGE_SCN_LNK_COMDAT ,
18
+ IMAGE_SCN_LNK_INFO , IMAGE_SCN_LNK_REMOVE , IMAGE_SCN_MEM_READ , IMAGE_SCN_MEM_WRITE ,
19
+ IMAGE_SYM_CLASS_EXTERNAL , IMAGE_SYM_CLASS_NULL , IMAGE_SYM_CLASS_SECTION ,
19
20
IMAGE_SYM_CLASS_STATIC , IMAGE_SYM_CLASS_WEAK_EXTERNAL , IMAGE_WEAK_EXTERN_SEARCH_ALIAS ,
20
21
} ;
21
22
use object:: pod:: bytes_of;
@@ -463,11 +464,14 @@ impl<'a> ObjectFactory<'a> {
463
464
/// Creates a NULL import descriptor. This is a small object file whcih
464
465
/// contains a NULL import descriptor. It is used to terminate the imports
465
466
/// from a specific DLL.
466
- fn create_null_import_descriptor ( & self ) -> Result < NewArchiveMember < ' _ > > {
467
+ ///
468
+ /// If `comdat` is set to true, the NULL import descriptor's section (`.idata$3`) will be
469
+ /// turned into a COMDAT section.
470
+ fn create_null_import_descriptor ( & self , comdat : bool ) -> Result < NewArchiveMember < ' _ > > {
467
471
let mut buffer = Vec :: new ( ) ;
468
472
469
473
const NUMBER_OF_SECTIONS : usize = 1 ;
470
- const NUMBER_OF_SYMBOLS : usize = 1 ;
474
+ let number_of_symbols = if comdat { 3 } else { 1 } ;
471
475
472
476
// COFF Header
473
477
let header = ImageFileHeader {
@@ -477,7 +481,7 @@ impl<'a> ObjectFactory<'a> {
477
481
pointer_to_symbol_table : u32 !( ( size_of :: < ImageFileHeader > ( ) + ( NUMBER_OF_SECTIONS * size_of :: < ImageSectionHeader > ( ) ) +
478
482
// .idata$3
479
483
size_of :: < ImageImportDescriptor > ( ) ) . try_into ( ) . unwrap ( ) ) ,
480
- number_of_symbols : u32 !( NUMBER_OF_SYMBOLS . try_into ( ) . unwrap ( ) ) ,
484
+ number_of_symbols : u32 !( number_of_symbols . try_into ( ) . unwrap ( ) ) ,
481
485
size_of_optional_header : u16 !( 0 ) ,
482
486
characteristics : u16 !( if self . is_64_bit ( ) {
483
487
0
@@ -506,6 +510,7 @@ impl<'a> ObjectFactory<'a> {
506
510
| IMAGE_SCN_CNT_INITIALIZED_DATA
507
511
| IMAGE_SCN_MEM_READ
508
512
| IMAGE_SCN_MEM_WRITE
513
+ | if comdat { IMAGE_SCN_LNK_COMDAT } else { 0 }
509
514
) ,
510
515
} ] ;
511
516
buffer. write_all ( bytes_of ( & section_table) ) ?;
@@ -521,16 +526,38 @@ impl<'a> ObjectFactory<'a> {
521
526
buffer. write_all ( bytes_of ( & import_descriptor) ) ?;
522
527
523
528
// Symbol Table
524
- let mut symbol_table: [ _ ; NUMBER_OF_SYMBOLS ] = [ ImageSymbol {
529
+ if comdat {
530
+ let symbol = ImageSymbol {
531
+ name : * b".idata$3" ,
532
+ value : u32 !( 0 ) ,
533
+ section_number : u16 !( 1 ) ,
534
+ typ : u16 !( 0 ) ,
535
+ storage_class : IMAGE_SYM_CLASS_STATIC ,
536
+ number_of_aux_symbols : 1 ,
537
+ } ;
538
+ let aux = ImageAuxSymbolSection {
539
+ length : u32 !( size_of :: < ImageImportDescriptor > ( ) . try_into ( ) . unwrap ( ) ) ,
540
+ number_of_relocations : u16 !( 0 ) ,
541
+ number_of_linenumbers : u16 !( 0 ) ,
542
+ check_sum : u32 !( 0 ) ,
543
+ selection : IMAGE_COMDAT_SELECT_ANY ,
544
+ number : u16 !( 0 ) ,
545
+ reserved : 0 ,
546
+ high_number : u16 !( 0 ) ,
547
+ } ;
548
+ buffer. write_all ( bytes_of ( & symbol) ) ?;
549
+ buffer. write_all ( bytes_of ( & aux) ) ?;
550
+ }
551
+ let mut null_descriptor_symbol = ImageSymbol {
525
552
name : [ 0 ; 8 ] ,
526
553
value : u32 !( 0 ) ,
527
554
section_number : u16 !( 1 ) ,
528
555
typ : u16 !( 0 ) ,
529
556
storage_class : IMAGE_SYM_CLASS_EXTERNAL ,
530
557
number_of_aux_symbols : 0 ,
531
- } ] ;
532
- set_name_to_string_table_entry ( & mut symbol_table [ 0 ] , size_of :: < u32 > ( ) ) ;
533
- buffer. write_all ( bytes_of ( & symbol_table ) ) ?;
558
+ } ;
559
+ set_name_to_string_table_entry ( & mut null_descriptor_symbol , size_of :: < u32 > ( ) ) ;
560
+ buffer. write_all ( bytes_of ( & null_descriptor_symbol ) ) ?;
534
561
535
562
// String Table
536
563
write_string_table ( & mut buffer, & [ NULL_IMPORT_DESCRIPTOR_SYMBOL_NAME ] ) ?;
@@ -826,6 +853,7 @@ pub fn write_import_library<W: Write + Seek>(
826
853
exports : & [ COFFShortExport ] ,
827
854
machine : MachineTypes ,
828
855
mingw : bool ,
856
+ comdat : bool ,
829
857
) -> Result < ( ) > {
830
858
let native_machine = if machine == MachineTypes :: ARM64EC {
831
859
MachineTypes :: ARM64
@@ -838,7 +866,7 @@ pub fn write_import_library<W: Write + Seek>(
838
866
839
867
members. push ( of. create_import_descriptor ( ) ?) ;
840
868
841
- members. push ( of. create_null_import_descriptor ( ) ?) ;
869
+ members. push ( of. create_null_import_descriptor ( comdat ) ?) ;
842
870
843
871
members. push ( of. create_null_thunk ( ) ?) ;
844
872
0 commit comments