@@ -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