[v2 PATCH] elf: Verify that there is only one default version

"H.J. Lu" <[email protected]>
Newsgroups gmane.comp.gnu.binutils
Message-ID <CAMe9rOqSQ4utzu+r-YQjCVnzTsQG22yuNRq5-Y=uVKfGQo_SHA@mail.gmail.com>
On Wed, Aug 26, 2026 at 11:35 AM H.J. Lu <[email protected]> wrote:
>
> When assigning the symbol version, verify that there is only one default
> version.
>

Here is the v2 patch to provide info of where multiple default versions
are defined:

ld -shared -o pr34550.so pr34550a.o pr34550b.o --version-script pr34550.t
/usr/local/bin/ld: pr34550.so: multiple default versions of `fmod':
`GLIBC_2.0' in pr34550a.o and `GLIBC_2.43' in pr34550b.o.
/usr/local/bin/ld: failed to set dynamic section sizes: bad value

-- 
H.J.
---
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.
v2-0001-elf-Verify-that-there-is-only-one-default-version.patch (text/x-patch, 4.7 KB)
From 43096b92b19323dbfbfe5ee41986c54032b96b92 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <[email protected]>
Date: Wed, 26 Aug 2026 11:29:39 +0800
Subject: [PATCH v2] 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]>
---
 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(-)
 create mode 100644 ld/testsuite/ld-elf/pr34550.d
 create mode 100644 ld/testsuite/ld-elf/pr34550.t
 create mode 100644 ld/testsuite/ld-elf/pr34550a.s
 create mode 100644 ld/testsuite/ld-elf/pr34550b.s

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
-- 
2.55.0
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.