Skip to content

Commit 33dbe5f

Browse files
committed
Add optional COMDAT to idata$3 in import files
1 parent 504d89a commit 33dbe5f

File tree

1 file changed

+42
-14
lines changed

1 file changed

+42
-14
lines changed

src/coff_import_file.rs

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,13 @@ use std::path::PathBuf;
1010
use std::str::from_utf8;
1111

1212
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,
1920
IMAGE_SYM_CLASS_STATIC, IMAGE_SYM_CLASS_WEAK_EXTERNAL, IMAGE_WEAK_EXTERN_SEARCH_ALIAS,
2021
};
2122
use 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

Comments
 (0)