@@ -10,12 +10,13 @@ use std::path::PathBuf;
1010use std:: str:: from_utf8;
1111
1212use 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 ,
1920 IMAGE_SYM_CLASS_STATIC , IMAGE_SYM_CLASS_WEAK_EXTERNAL , IMAGE_WEAK_EXTERN_SEARCH_ALIAS ,
2021} ;
2122use object:: pod:: bytes_of;
@@ -463,11 +464,14 @@ impl<'a> ObjectFactory<'a> {
463464 /// Creates a NULL import descriptor. This is a small object file whcih
464465 /// contains a NULL import descriptor. It is used to terminate the imports
465466 /// 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 < ' _ > > {
467471 let mut buffer = Vec :: new ( ) ;
468472
469473 const NUMBER_OF_SECTIONS : usize = 1 ;
470- const NUMBER_OF_SYMBOLS : usize = 1 ;
474+ let number_of_symbols = if comdat { 3 } else { 1 } ;
471475
472476 // COFF Header
473477 let header = ImageFileHeader {
@@ -477,7 +481,7 @@ impl<'a> ObjectFactory<'a> {
477481 pointer_to_symbol_table : u32 !( ( size_of :: < ImageFileHeader > ( ) + ( NUMBER_OF_SECTIONS * size_of :: < ImageSectionHeader > ( ) ) +
478482 // .idata$3
479483 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 ( ) ) ,
481485 size_of_optional_header : u16 !( 0 ) ,
482486 characteristics : u16 !( if self . is_64_bit ( ) {
483487 0
@@ -506,6 +510,7 @@ impl<'a> ObjectFactory<'a> {
506510 | IMAGE_SCN_CNT_INITIALIZED_DATA
507511 | IMAGE_SCN_MEM_READ
508512 | IMAGE_SCN_MEM_WRITE
513+ | if comdat { IMAGE_SCN_LNK_COMDAT } else { 0 }
509514 ) ,
510515 } ] ;
511516 buffer. write_all ( bytes_of ( & section_table) ) ?;
@@ -521,16 +526,38 @@ impl<'a> ObjectFactory<'a> {
521526 buffer. write_all ( bytes_of ( & import_descriptor) ) ?;
522527
523528 // 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 {
525552 name : [ 0 ; 8 ] ,
526553 value : u32 !( 0 ) ,
527554 section_number : u16 !( 1 ) ,
528555 typ : u16 !( 0 ) ,
529556 storage_class : IMAGE_SYM_CLASS_EXTERNAL ,
530557 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 ) ) ?;
534561
535562 // String Table
536563 write_string_table ( & mut buffer, & [ NULL_IMPORT_DESCRIPTOR_SYMBOL_NAME ] ) ?;
@@ -826,6 +853,7 @@ pub fn write_import_library<W: Write + Seek>(
826853 exports : & [ COFFShortExport ] ,
827854 machine : MachineTypes ,
828855 mingw : bool ,
856+ comdat : bool ,
829857) -> Result < ( ) > {
830858 let native_machine = if machine == MachineTypes :: ARM64EC {
831859 MachineTypes :: ARM64
@@ -838,7 +866,7 @@ pub fn write_import_library<W: Write + Seek>(
838866
839867 members. push ( of. create_import_descriptor ( ) ?) ;
840868
841- members. push ( of. create_null_import_descriptor ( ) ?) ;
869+ members. push ( of. create_null_import_descriptor ( comdat ) ?) ;
842870
843871 members. push ( of. create_null_thunk ( ) ?) ;
844872
0 commit comments