[binutils-gdb] elf: Verify that there is only one default version

"H.J. Lu via Binutils-cvs" <[email protected]>
Newsgroups gmane.comp.gnu.binutils.cvs
Message-ID <[email protected]>
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=b981d8e9bcecdf2a45cb46ced2530e7b13034a19

commit b981d8e9bcecdf2a45cb46ced2530e7b13034a19
Author: H.J. Lu <[email protected]>
Date:   Wed Aug 26 11:29:39 2026 +0800

    elf: Verify that there is only one default version
    
    When assigning the symbol version, verify that there is only one default
    version.
    
    bfd/
    
            PR ld/34550
            * elflink.c (_bfd_elf_link_assign_sym_version): Verify that there
            is only one default version.
    
    ld/
    
            PR ld/34550
            * testsuite/ld-elf/pr34550.d: New test.
            * testsuite/ld-elf/pr34550.t: Likewise.
            * testsuite/ld-elf/pr34550a.s: Likewise.
            * testsuite/ld-elf/pr34550b.s: Likewise.
    
    Signed-off-by: H.J. Lu <[email protected]>

Diff:
---
 bfd/elflink.c                  | 52 +++++++++++++++++++++++++++++++++++++++++-
 ld/testsuite/ld-elf/pr34550.d  |  6 +++++
 ld/testsuite/ld-elf/pr34550.t  | 13 +++++++++++
 ld/testsuite/ld-elf/pr34550a.s |  5 ++++
 ld/testsuite/ld-elf/pr34550b.s |  6 +++++
 5 files changed, 81 insertions(+), 1 deletion(-)

diff --git a/bfd/elflink.c b/bfd/elflink.c
index 09eaacc8497..e7348901b8c 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -2697,10 +2697,14 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
   if (p != NULL && h->verinfo.vertree == NULL)
     {
       struct bfd_elf_version_tree *t;
+      bool default_version = false;
 
       ++p;
       if (*p == ELF_VER_CHR)
-	++p;
+	{
+	  default_version = true;
+	  ++p;
+	}
 
       /* If there is no version string, we can just return out.  */
       if (*p == '\0')
@@ -2714,6 +2718,52 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
 
       if (hide)
 	obed->elf_backend_hide_symbol (info, h, true);
+      else if (default_version)
+	{
+	  /* Get the unversioned symbol for the default version.  */
+	  struct elf_link_hash_entry *h_u;
+	  size_t size = p - h->root.root.string - 1;
+	  char *unversioned_name = bfd_malloc (size);
+	  if (unversioned_name == NULL)
+	    {
+	      sinfo->failed = true;
+	      return false;
+	    }
+	  memcpy (unversioned_name, h->root.root.string, size - 1);
+	  unversioned_name[size - 1] = 0;
+	  h_u = elf_link_hash_lookup (elf_hash_table (info),
+				      unversioned_name, false,
+				      false, false);
+
+	  /* There must be an unversioned symbol. */
+	  if (h_u == NULL)
+	    abort ();
+
+	  while (h_u->root.type == bfd_link_hash_indirect
+		 || h_u->root.type == bfd_link_hash_warning)
+	    h_u = (struct elf_link_hash_entry *) h_u->root.u.i.link;
+
+	  /* Verify that there is only one default version.  */
+	  if (h_u->versioned != versioned_hidden
+	      && h_u->verinfo.vertree != h->verinfo.vertree)
+	    {
+	      /* xgettext:c-format */
+	      info->callbacks->einfo
+		(_("%X%P: %pB: multiple default versions of `%s': "
+		   "`%s' in %pB and `%s' in %pB.\n"),
+		 info->output_bfd, unversioned_name,
+		 h_u->verinfo.vertree->name,
+		 h_u->root.u.def.section->owner,
+		 h->verinfo.vertree->name,
+		 h->root.u.def.section->owner);
+	      bfd_set_error (bfd_error_bad_value);
+	      sinfo->failed = true;
+	      free (unversioned_name);
+	      return false;
+	    }
+
+	  free (unversioned_name);
+	}
 
       /* If we are building an application, we need to create a
 	 version node for this version.  */
diff --git a/ld/testsuite/ld-elf/pr34550.d b/ld/testsuite/ld-elf/pr34550.d
new file mode 100644
index 00000000000..260c6cab1ee
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr34550.d
@@ -0,0 +1,6 @@
+#source: pr34550a.s
+#source: pr34550b.s
+#target: [check_shared_lib_support]
+#as:
+#ld: -shared --version-script=pr34550.t
+#error: multiple default versions of `fmod': `GLIBC_2.0' in tmpdir/pr34550a.o and `GLIBC_2.43' in tmpdir/pr34550b.o.
diff --git a/ld/testsuite/ld-elf/pr34550.t b/ld/testsuite/ld-elf/pr34550.t
new file mode 100644
index 00000000000..37dff255cdc
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr34550.t
@@ -0,0 +1,13 @@
+GLIBC_2.0 {
+  global:
+    fmod;
+  local:
+    *;
+};
+
+GLIBC_2.43 {
+  global:
+    fmod;
+  local:
+    *;
+} GLIBC_2.0;
diff --git a/ld/testsuite/ld-elf/pr34550a.s b/ld/testsuite/ld-elf/pr34550a.s
new file mode 100644
index 00000000000..fea245035b9
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr34550a.s
@@ -0,0 +1,5 @@
+	.text
+	.type	fmod,%function
+	.globl fmod
+fmod:
+	.dc.a 0
diff --git a/ld/testsuite/ld-elf/pr34550b.s b/ld/testsuite/ld-elf/pr34550b.s
new file mode 100644
index 00000000000..babe762f882
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr34550b.s
@@ -0,0 +1,6 @@
+	.text
+	.type	fmod_new,%function
+	.globl fmod_new
+fmod_new:
+	.dc.a 0
+	.symver fmod_new, fmod@@GLIBC_2.43
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.