diff --git a/libwild/src/elf_writer.rs b/libwild/src/elf_writer.rs index df1d1ea4d..63efa59e9 100644 --- a/libwild/src/elf_writer.rs +++ b/libwild/src/elf_writer.rs @@ -3857,6 +3857,42 @@ fn write_regular_object_dynamic_symbol_definition<'data>( format!("Failed to copy dynamic {}", layout.symbol_debug(symbol_id)) })?; } + } else if sym.is_common(LittleEndian) { + let symbol_id = sym_def.symbol_id; + let resolution = layout.local_symbol_resolution(symbol_id).with_context(|| { + format!( + "Tried to write dynamic symbol definition without a resolution: {}", + layout.symbol_debug(symbol_id) + ) + })?; + + let mut sym_value = resolution.value(); + + // As common symbols are denoted by setting shndx=SHN_COMMON which is a special section, + // we need to put them manually into BSS/TBSS sections depending on whether they are thread + // local or not. + let section_id = if sym.st_type() == STT_TLS { + sym_value -= layout.tls_start_address(); + output_section_id::TBSS + } else { + output_section_id::BSS + }; + let section_id = layout.output_sections.primary_output_section(section_id); + + dynamic_symbol_writer + .copy_symbol(sym, name, section_id, sym_value, ValueFlags::empty()) + .with_context(|| { + format!("Failed to copy dynamic {}", layout.symbol_debug(symbol_id)) + })?; + } else if sym.is_absolute(LittleEndian) { + dynamic_symbol_writer + .copy_absolute_symbol(sym, name, ValueFlags::empty()) + .with_context(|| { + format!( + "Failed to absolute {}", + layout.symbol_debug(sym_def.symbol_id) + ) + })?; } else { dynamic_symbol_writer .copy_symbol_shndx(sym, name, 0, 0, ValueFlags::empty()) diff --git a/wild/tests/integration_tests.rs b/wild/tests/integration_tests.rs index 46e2e324a..38cc6177c 100644 --- a/wild/tests/integration_tests.rs +++ b/wild/tests/integration_tests.rs @@ -3547,6 +3547,8 @@ fn integration_test( "non-alloc.s", "gnu-unique.c", "symbol-versions.c", + "common-shared.c", + "absolute-symbol.s", "simple-version-script.c", "mixed-verdef-verneed.c", "copy-relocations.c", diff --git a/wild/tests/sources/absolute-symbol.s b/wild/tests/sources/absolute-symbol.s new file mode 100644 index 000000000..e86b53e32 --- /dev/null +++ b/wild/tests/sources/absolute-symbol.s @@ -0,0 +1,15 @@ +//#LinkArgs:-shared -z now +//#RunEnabled:false +//#DiffIgnore:section.got +//#ExpectSym:abs_sym address=0xCAFECAFE +//#ExpectDynSym:abs_sym address=0xCAFECAFE + +// TODO: checkout those differences later +//#DiffIgnore:segment.RISCV_ATTRIBUTES.alignment +//#DiffIgnore:segment.RISCV_ATTRIBUTES.flags +//#DiffIgnore:riscv_attributes..riscv.attributes +//#DiffIgnore:riscv_attributes.arch +//#DiffIgnore:riscv_attributes.stack_align + +.global abs_sym +.set abs_sym, 0xCAFECAFE diff --git a/wild/tests/sources/common-shared-1.c b/wild/tests/sources/common-shared-1.c new file mode 100644 index 000000000..0116b7caa --- /dev/null +++ b/wild/tests/sources/common-shared-1.c @@ -0,0 +1,5 @@ +extern int data[]; +int data[100]; + +extern __thread int tvar[]; +__thread int tvar[100] __attribute__((common)); diff --git a/wild/tests/sources/common-shared.c b/wild/tests/sources/common-shared.c new file mode 100644 index 000000000..934d85657 --- /dev/null +++ b/wild/tests/sources/common-shared.c @@ -0,0 +1,15 @@ +//#CompArgs:-fcommon +//#Object:common-shared-1.c +//#LinkArgs:-shared -z now +//#RunEnabled:false +//#DiffIgnore:section.got +//#ExpectSym:data section=".bss",size=400 +//#ExpectDynSym:data section=".bss",size=400 +//#ExpectSym:tvar section=".tbss",size=400,address=0 +//#ExpectDynSym:tvar section=".tbss",size=400,address=0 + +extern int data[]; +int data[10]; + +extern __thread int tvar[]; +__thread int tvar[10] __attribute__((common));