readelf: Display the base symbol version as empty string

Update readelf to display the base symbol version as

Symbol table for image contains 5 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000000003008     0 OBJECT  GLOBAL DEFAULT   10 bar@@
     2: 0000000000000000     0 OBJECT  GLOBAL DEFAULT  ABS VERS_1
     3: 0000000000003008     0 OBJECT  GLOBAL DEFAULT   10 bar@@VERS_1
     4: 0000000000003000     0 OBJECT  GLOBAL DEFAULT   10 foo@

instead of

Symbol table for image contains 5 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000000003008     0 OBJECT  GLOBAL DEFAULT   10 bar
     2: 0000000000000000     0 OBJECT  GLOBAL DEFAULT  ABS VERS_1
     3: 0000000000003008     0 OBJECT  GLOBAL DEFAULT   10 bar@@VERS_1
     4: 0000000000003000     0 OBJECT  GLOBAL DEFAULT   10 foo

That is bar@@ and foo@ vs bar and foo.

binutils/

	PR binutils/33599
	* readelf.c (process_version_sections): Replace 0x8001 with
	(VERSYM_HIDDEN | VERSYM_BASE).
	(get_symbol_version_string): Likewise.  Return "" for the base
	version.

include/

	PR binutils/33599
	* elf/common.h (VERSYM_BASE): New.

ld/

	PR binutils/33599
	* testsuite/ld-elf/pr33599.d: New file.
	* testsuite/ld-elf/pr33599.map: Likewise.
	* testsuite/ld-elf/pr33599.s: Likewise.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
This commit is contained in:
H.J. Lu
2025-11-06 08:20:26 +08:00
parent 767c92a13e
commit 2be0f2da21
5 changed files with 49 additions and 2 deletions

View File

@@ -14074,7 +14074,7 @@ process_version_sections (Filedata * filedata)
while (ivn.vn_next);
}
if (data[cnt + j] != 0x8001
if (data[cnt + j] != (VERSYM_HIDDEN | VERSYM_BASE)
&& filedata->version_info[DT_VERSIONTAGIDX (DT_VERDEF)])
{
Elf_Internal_Verdef ivd;
@@ -14500,6 +14500,10 @@ get_symbol_version_string (Filedata *filedata,
*sym_info = (vers_data & VERSYM_HIDDEN) != 0 ? symbol_hidden : symbol_public;
max_vd_ndx = 0;
/* Return the empty string for the base version. */
if ((vers_data & VERSYM_VERSION) == VERSYM_BASE)
return "";
/* Usually we'd only see verdef for defined symbols, and verneed for
undefined symbols. However, symbols defined by the linker in
.dynbss for variables copied from a shared library in order to
@@ -14510,7 +14514,7 @@ get_symbol_version_string (Filedata *filedata,
verneed. .dynbss might not be mapped to a SHT_NOBITS section. */
if (psym->st_shndx != SHN_UNDEF
&& vers_data != 0x8001
&& vers_data != (VERSYM_HIDDEN | VERSYM_BASE)
&& filedata->version_info[DT_VERSIONTAGIDX (DT_VERDEF)])
{
Elf_Internal_Verdef ivd;

View File

@@ -1377,6 +1377,11 @@
#define VERSYM_HIDDEN 0x8000
/* This flag appears in a Versym structure. It means that the symbol
is the base version. */
#define VERSYM_BASE 0x0001
/* This is the mask for the rest of the Versym information. */
#define VERSYM_VERSION 0x7fff

View File

@@ -0,0 +1,11 @@
#ld: -shared --version-script $srcdir/$subdir/pr33599.map
#readelf : --dyn-syms --wide
#target: *-*-linux* *-*-gnu* *-*-solaris* arm*-*-uclinuxfdpiceabi
#xfail: ![check_shared_lib_support]
Symbol table '\.dynsym' contains [0-9]+ entries:
#...
+[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +OBJECT +GLOBAL +DEFAULT +[0-9]+ +bar@@
#...
+[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +OBJECT +GLOBAL +DEFAULT +[0-9]+ +foo@
#pass

View File

@@ -0,0 +1,7 @@
VERS_1 {
global:
foo;
bar;
local:
*;
};

View File

@@ -0,0 +1,20 @@
.globl foo
.globl foo_base
.type foo, %object
.type foo_base, %object
.data
foo:
foo_base:
.dc.a bar
.symver foo_base,foo@
.globl bar
.globl bar_base
.type bar, %object
.type bar_base, %object
bar:
bar_base:
.dc.a foo
.symver bar_base,bar@@