From 43158eaa713b665c375620c0545c708795c2a0a3 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Tue, 28 Jul 2026 18:01:53 +0900 Subject: [PATCH] tccelf: consider DSO symbols for PROVIDE An input shared object can be the only place where a conventional boundary name is referenced or defined. In that case the regular symbol table has no entry, but native ELF linkers still synthesize the executable definition so that it participates in dynamic symbol resolution. Consult the input dynamic symbol table before treating a plain boundary name as unreferenced. Exercise the case with a DSO-defined end symbol whose address must be interposed by the executable's final boundary. --- tccelf.c | 8 ++++++-- tests/tests2/151+_dso_linker_symbol.c | 6 ++++++ tests/tests2/151_dso_linker_symbol.c | 12 ++++++++++++ tests/tests2/151_dso_linker_symbol.expect | 1 + tests/tests2/Makefile | 15 ++++++++++++--- 5 files changed, 37 insertions(+), 5 deletions(-) create mode 100644 tests/tests2/151+_dso_linker_symbol.c create mode 100644 tests/tests2/151_dso_linker_symbol.c create mode 100644 tests/tests2/151_dso_linker_symbol.expect diff --git a/tccelf.c b/tccelf.c index 4837936d..049d9cda 100644 --- a/tccelf.c +++ b/tccelf.c @@ -1586,9 +1586,13 @@ static void provide_linker_sym(TCCState *s1, const char *name, { int sym_index = find_elf_sym(symtab_section, name); - if (!sym_index - || ((ElfW(Sym) *)symtab_section->data)[sym_index].st_shndx != SHN_UNDEF) + if (sym_index) { + if (((ElfW(Sym) *)symtab_section->data)[sym_index].st_shndx != SHN_UNDEF) + return; + } else if (!s1->dynsymtab_section + || !find_elf_sym(s1->dynsymtab_section, name)) { return; + } set_linker_sym(s1, name, sec, offs); } diff --git a/tests/tests2/151+_dso_linker_symbol.c b/tests/tests2/151+_dso_linker_symbol.c new file mode 100644 index 00000000..b3a9dcf1 --- /dev/null +++ b/tests/tests2/151+_dso_linker_symbol.c @@ -0,0 +1,6 @@ +char end = 7; + +char *get_dso_end(void) +{ + return &end; +} diff --git a/tests/tests2/151_dso_linker_symbol.c b/tests/tests2/151_dso_linker_symbol.c new file mode 100644 index 00000000..26e5491c --- /dev/null +++ b/tests/tests2/151_dso_linker_symbol.c @@ -0,0 +1,12 @@ +#include + +extern char _end[]; +extern char *get_dso_end(void); + +int main(void) +{ + int errors = get_dso_end() != _end; + + printf("DSO linker symbol errors: %d\n", errors); + return errors; +} diff --git a/tests/tests2/151_dso_linker_symbol.expect b/tests/tests2/151_dso_linker_symbol.expect new file mode 100644 index 00000000..6e81c47a --- /dev/null +++ b/tests/tests2/151_dso_linker_symbol.expect @@ -0,0 +1 @@ +DSO linker symbol errors: 0 diff --git a/tests/tests2/Makefile b/tests/tests2/Makefile index 1c094d42..d8c4ebb8 100644 --- a/tests/tests2/Makefile +++ b/tests/tests2/Makefile @@ -38,7 +38,7 @@ ifeq ($(CONFIG_bcheck),no) endif ifeq ($(CONFIG_dll),no) SKIP += 113_btdll.test 147_def_library.test # no shared lib support yet - SKIP += 149_end_copy_reloc.test + SKIP += 149_end_copy_reloc.test 151_dso_linker_symbol.test endif ifeq (-$(findstring gcc,$(CC))-,--) SKIP += $(patsubst %.expect,%.test,$(GEN-ALWAYS)) @@ -56,7 +56,7 @@ ifeq (-$(CONFIG_WIN32)-,-yes-) SKIP += 124_atomic_counter.test # No pthread support SKIP += 144_tls.test 146_tls_extern.test # TLS runtime not supported SKIP += 148_linker_symbols.test 149_end_copy_reloc.test # ELF linker tests - SKIP += 150_linker_boundaries.test + SKIP += 150_linker_boundaries.test 151_dso_linker_symbol.test endif ifneq (,$(filter OpenBSD FreeBSD NetBSD,$(TARGETOS))) SKIP += 106_versym.test # no pthread_condattr_setpshared @@ -70,7 +70,7 @@ endif ifeq ($(CONFIG_OSX),yes) SKIP += 144_tls.test 146_tls_extern.test # TLS runtime not supported on Mach-O SKIP += 148_linker_symbols.test 149_end_copy_reloc.test # ELF linker tests - SKIP += 150_linker_boundaries.test + SKIP += 150_linker_boundaries.test 151_dso_linker_symbol.test endif ifeq ($(CONFIG_pie),yes) SKIP += 149_end_copy_reloc.test # PIE executables do not use copy relocations @@ -183,6 +183,15 @@ GEN-ALWAYS = ./$(basename $@).exe \ ) +# A linker symbol needed only by a DSO must be provided by the executable. +151_dso_linker_symbol.test: NORUN = true +151_dso_linker_symbol.test: T1 = ( \ + $(TCC) -shared $(subst 151,151+,$1) -o 151_dso_linker_symbol$(DLLSUF) && \ + $(TCC) $1 ./151_dso_linker_symbol$(DLLSUF) -Wl,-rpath=. \ + -o $(basename $@).exe && \ + ./$(basename $@).exe \ + ) + 112_backtrace.test: FLAGS += -dt -b 112_backtrace.test 113_btdll.test 126_bound_global.test: FILTER += \ -e 's;[0-9A-Fa-fx]\{5,\};........;g' \